Firestore嵌套集合数据获取异常:内存溢出/应用崩溃求助
Firestore嵌套集合数据获取问题排查与修复
问题描述
我有Firestore嵌套集合结构doctors→visits,想要获取该集合及子集合的全部数据并存入列表,用于ListView展示。
数据模型如下:
class allReport { late String? date; late String? doctorNote; String? doctoreName; late String? marketerNote; late String? id; allReport({ required this.date, required this.doctorNote, required this.marketerNote, required this.id, required this.doctoreName }); static allReport fromJson( Map<String, dynamic> json, String id, String doctoreName) => allReport( id: id, doctoreName: doctoreName, doctorNote: json['doctorNote'], date: json['date'], marketerNote: json['marketerNote'], ); }
我尝试用以下代码获取数据,通过doc.reference.parent.parent获取visits文档的父级ID,进而获取父级数据:
List<allReport> _docReports = []; List<allReport> _filtereddocReports = []; Future<List<allReport>> getAlldocsData() async { var col = await _firestore.collectionGroup('visits'); var snapshot_child = await col.get(); snapshot_child.docs.map((doc) async { var ChildDocument = doc; var snapshot_parent = await _firestore .collection('doctors') .doc(ChildDocument.reference.parent.parent?.id) .get(); _docReports = allReport.fromJson( ChildDocument.data() ,snapshot_parent.data()?['name'] ,doc.reference.parent.parent?.id ?? '') as List<allReport>; }).toList(); print('**********************${_docReports.map((e) => e.doctoreName)}'); setState(() { _filtereddocReports = _docReports; }); return _filtereddocReports; }
当前代码无法打印数据,还出现“内存溢出”错误,偶尔应用崩溃,需要排查问题。
问题原因分析
- 异步处理失效:
map内的async回调返回Future,但直接调用toList()不会等待所有异步任务完成,导致后续代码在数据未处理完时就执行,_docReports始终为空。 - 类型转换错误:
allReport.fromJson返回单个对象,却被强行转为List<allReport>,触发类型异常,进而引发内存溢出或崩溃。 - 列表赋值逻辑错误:每次循环都用单个对象覆盖
_docReports,而非添加元素,即使无类型错误,最终列表也只会保留最后一条数据。 - 参数传递错误:
fromJson的参数顺序与构造函数不匹配,把医生ID传给了id参数,不符合业务逻辑。
修正后的代码
List<allReport> _docReports = []; List<allReport> _filtereddocReports = []; Future<List<allReport>> getAlldocsData() async { // 清空列表,避免重复添加数据 _docReports.clear(); // 获取所有visits集合的文档 final snapshotChild = await _firestore.collectionGroup('visits').get(); // 等待所有异步请求完成 await Future.wait(snapshotChild.docs.map((doc) async { // 获取父级doctor文档ID,为空则跳过 final doctorId = doc.reference.parent.parent?.id; if (doctorId == null) return; // 获取父级doctor文档数据 final snapshotParent = await _firestore.collection('doctors').doc(doctorId).get(); final doctorName = snapshotParent.data()?['name'] ?? ''; // 转换为allReport对象并添加到列表 final report = allReport.fromJson( doc.data(), doc.id, // visits文档ID作为report的id doctorName // 医生名称作为doctoreName ); _docReports.add(report); })); print('**********************${_docReports.map((e) => e.doctoreName)}'); setState(() { _filtereddocReports = List.from(_docReports); // 创建副本避免引用问题 }); return _filtereddocReports; }
额外优化建议
- 冗余字段优化性能:如果visits数据量较大,逐个请求doctor文档会产生大量网络请求,建议在visits文档中冗余存储
doctorName字段,直接从visits文档读取即可,无需额外请求父集合。 - 实时数据监听:若需要实时更新数据,可使用
collectionGroup('visits').snapshots()监听数据流,替代单次get()请求。 - 代码规范修正:遵循Dart命名规范,将类名
allReport改为大驼峰格式AllReport。
内容的提问来源于stack exchange,提问作者fyry J4
相关产品推荐
相关产品推荐

