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, }); }
问题根因
- 读写路径不匹配:写入数据时路径为
incomingRequests/${requestModel.id}/${Fcm.getUid()},但读取时路径为incomingRequests/${userId},两个路径层级完全不一致,读取到的是结构不符合预期的脏数据。 - 类型转换无校验:Firebase返回的快照值默认是
Map<dynamic, dynamic>类型,你没有判断嵌套值的类型就直接强转、用下标取字段,当读到非预期结构的数据时,会在forEach循环内抛出类型错误。 - 异常被静默吞掉:
Stream.listen异步回调内的异常不会被外层的try/catch捕获,你没有设置onError回调,报错没有任何打印,表现出来就是add操作看似执行了,实际因为报错中断,列表始终为空。 - 调试打印误导:直接打印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
相关产品推荐
相关产品推荐

