You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Firebase数据存入Model列表后丢失问题求助

问题描述

从Firebase Database获取数据后,尝试将其存入自定义Model类对应的列表中。控制台打印测试确认接收到的原始数据正常,但一旦将数据添加到Model类实例后数据就会消失。

相关代码

Provider类加载逻辑

import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:local_stuffs_notification/apis/fcm.dart';
import 'package:local_stuffs_notification/models/request_model.dart';
import 'package:shared_preferences/shared_preferences.dart';

class IncomingRequest with ChangeNotifier {
  List<RequestModel> _incomingRequests = [];
  IncomingRequest(this._incomingRequests);

  List<RequestModel> get incomingRequest {
    return [..._incomingRequests];
  }

  Future<void> setIncomingRequest(RequestModel requestModel) async {
    try {
      DatabaseReference reference =
          FirebaseDatabase.instance.ref("incomingRequests");
      reference.child(requestModel.id).child(Fcm.getUid()).set(
        {
          "name": requestModel.name.toString(),
          "phone": requestModel.phone.toString(),
          "email": requestModel.email.toString(),
          "fcmToken": requestModel.fcmToken.toString(),
        },
      );
      notifyListeners();
    } catch (error) {
      rethrow;
    }
  }

  Future<void> loadIncomingRequests() async {
    try {
      SharedPreferences preferences = await SharedPreferences.getInstance();
      DatabaseReference reference = FirebaseDatabase.instance
          .ref('incomingRequests/${preferences.getString('userId')!}');
      Stream<DatabaseEvent> stream = reference.onValue;
      stream.listen((DatabaseEvent event) {
        print(event.snapshot.value);
        final data = event.snapshot.value as Map;
        print('data: $data');
        final List<RequestModel> loadedRequest = [];
        data.forEach(
          (key, value) {
            print('requestData: ${value['name']}');
            loadedRequest.add(
              RequestModel(
                id: key.toString(),
                name: value['name'].toString(),
                fcmToken: value['fcmToken'].toString(),
                phone: value['phone'].toString(),
                email: value['email'].toString(),
              ),
            );
            print(loadedRequest);
          },
        );
        _incomingRequests = loadedRequest;
        print('LoadedRequests: $loadedRequest');
        notifyListeners();
      });
    } catch (error) {
      rethrow;
    }
  }
}

自定义Model类

class RequestModel {
  final String id;
  final String name;
  final String fcmToken;
  final String phone;
  final String email;

  RequestModel({
    required this.id,
    required this.name,
    required this.fcmToken,
    required this.phone,
    required this.email,
  });
}
问题根因
  1. 读写路径不匹配:写入数据时路径为incomingRequests/${requestModel.id}/${Fcm.getUid()},但读取时路径为incomingRequests/${userId},两个路径层级完全不一致,读取到的是结构不符合预期的脏数据。
  2. 类型转换无校验:Firebase返回的快照值默认是Map<dynamic, dynamic>类型,你没有判断嵌套值的类型就直接强转、用下标取字段,当读到非预期结构的数据时,会在forEach循环内抛出类型错误。
  3. 异常被静默吞掉:Stream.listen异步回调内的异常不会被外层的try/catch捕获,你没有设置onError回调,报错没有任何打印,表现出来就是add操作看似执行了,实际因为报错中断,列表始终为空。
  4. 调试打印误导:直接打印List对象时Dart存在截断、类型转换显示问题,会让你误以为列表是空的。
修复方案
  • 第一步先对齐读写路径,确保读取的节点层级和写入时完全对应。
  • 解析数据时增加完整的空判断、类型判断,不要直接强转:
stream.listen((DatabaseEvent event) {
  // 空场景直接重置列表
  if (event.snapshot.value == null) {
    _incomingRequests = [];
    notifyListeners();
    return;
  }
  final rawData = event.snapshot.value;
  final List<RequestModel> loadedRequest = [];
  if (rawData is Map) {
    rawData.forEach((key, value) {
      // 校验嵌套值是Map结构再取字段,避免类型错误
      if (value is Map) {
        loadedRequest.add(
          RequestModel(
            id: key.toString(),
            name: (value['name'] ?? '').toString(),
            fcmToken: (value['fcmToken'] ?? '').toString(),
            phone: (value['phone'] ?? '').toString(),
            email: (value['email'] ?? '').toString(),
          ),
        );
      }
    });
  }
  _incomingRequests = loadedRequest;
  // 调试时打印长度和单个字段,不要直接打印整个List
  print('加载完成,共${loadedRequest.length}条数据');
  notifyListeners();
}, onError: (err) {
  // 打印Stream回调内的异常,方便排查
  print('数据解析错误: $err');
});

内容的提问来源于stack exchange,提问作者shiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:18:22