Flutter无法从Firebase Firestore获取Map类型package数据
问题:无法从Firestore获取package数据
数据模型

相关代码
Services类
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:ilab/services/User.dart'; class Services { final _db = FirebaseFirestore.instance.collection('tests'); // 从快照转换为测试列表 List<Test> _testsListFromSnapshot(QuerySnapshot snapshot) { return snapshot.docs.map((DocumentSnapshot document) { Map<String, dynamic> data = document.data() as Map<String, dynamic>; return Test( details: data['details'] ?? '', name: data['name'] ?? '', price: data['price'] ?? '', type: data['type'] ?? '', package: data['package'] ?? '', // 此处存在问题:默认值应为空Map而非空字符串 indication: data['indication'] ?? '', method: data['method'] ?? '', general: data['general'] ?? '', specimen_type: data['specimen_type'] ?? '', time: data['time'] ?? '', notes: data['notes'] ?? '', preanalytic_precautions: data['preanalytic_precautions'] ?? '', ref_rangeUnits: data['ref_rangeUnits'] ?? '', add: data['add'] ?? '', dateFrom: data['dateFrom'] ?? '', dateTo: data['dateTo'] ?? '', ); }).toList(); } // 获取测试数据流 Stream<List<Test>> get Tests { return _db.snapshots().map(_testsListFromSnapshot); } }
Test实体类
import 'package:cloud_firestore/cloud_firestore.dart'; class Test{ final String details; final String name; final String price; final String type; final String general ; final String preanalytic_precautions ; final String indication ; final String specimen_type ; final String time ; final String ref_rangeUnits ; final String notes ; final String method ; final String add; final String dateFrom; final String dateTo; final Map package; // 建议指定类型为Map<String, dynamic>? Test({ this.details, this.name, this.price, this.type, this.package, this.general, this.time, this.indication, this.method, this.notes, this.preanalytic_precautions, this.ref_rangeUnits, this.specimen_type, this.add, this.dateFrom, this.dateTo }); factory Test.fromDocument(DocumentSnapshot doc){ return Test( details: doc['details'], name: doc['name'], price: doc['price'], type: doc['type'], method: doc['method'], indication: doc['indication'], preanalytic_precautions: doc['preanalytic_precautions'], specimen_type: doc['specimen_type'], general: doc['general'], ref_rangeUnits: doc['ref_rangeUnits'], time: doc['time'], notes: doc['notes'], add: doc['add'], dateTo: doc['dateTo'], dateFrom: doc['dateFrom'], package: doc['package'], ); } }
UI代码
ListView.builder( shrinkWrap: true, padding: EdgeInsets.all(1.h), controller: scrollController, scrollDirection: Axis.vertical, itemBuilder: (BuildContext context, int index) { if (filteredTests != null) { return Card( child: Padding( padding: EdgeInsets.all(5.0), child: _card(index)), ); } else { return Center(child: Text('لا توجد بيانات ',style: TextStyle(fontFamily: 'Cairo'))); } }, itemCount: filteredTests.length, itemExtent: 240.0, ) // 根据数据类型返回不同卡片样式 Widget _card(int index) { try { Color selectedColour(index) { Color c; if (index % 4 == 0) c = Colors.cyan; if (index % 4 == 1) c = Colors.blueGrey; if (index % 4 == 2) c = Colors.blue; if (index % 4 == 3) c = Color(0xFFea9999); return c; } if (filteredTests[index].type == 'باقة') { return PackageCardDesign( packageName: filteredTests[index].name, package: '', price: '${filteredTests[index].price} YR', details: filteredTests[index].details.toLowerCase(), colour: selectedColour(index), icon: Icons.ac_unit_outlined, type: filteredTests[index].type, ); } } catch (e) { print(e); } }
尝试的获取代码及错误
尝试了多种方式读取package数据,例如:
// 方法1 for (var entry in filteredTests[index].package.entries) { print(entry.key); print(entry.value); } // 方法2 List St = filteredTests[index].package.map((k,v) => MapEntry(k,v)).values.toList(); print (St); // 方法3 Map<String, dynamic> data = filteredTests[index].package; for (var entry in data['package'].entries) { print(entry.key); print(entry.value); }
每次都触发错误:
NoSuchMethodError: 方法'[]'在null上被调用。
I/flutter ( 3668): Receiver: null
I/flutter ( 3668): Tried calling:
问题原因及解决方法
核心问题
- 类型不匹配:Services类中
package字段的默认值设为了空字符串'',但Test类中package定义为Map类型。当Firestore中没有package字段时,空字符串会被赋值给package,导致后续调用Map方法(如entries、[])时报错。 - 空值未处理:未先判断
package是否为null就直接调用其方法,触发空指针异常。
解决方案
- 修正Services类的默认值:将
package的默认值改为空Map,而非空字符串:
package: data['package'] ?? <String, dynamic>{},
- 明确Test类的类型:将
package字段类型改为可空的Map类型,避免类型错误:
final Map<String, dynamic>? package;
- 安全读取package数据:在使用前先判断是否为null,再进行遍历:
// 在_card方法中读取package的示例 if (filteredTests[index].type == 'باقة') { final packageData = filteredTests[index].package; String packageContent = ''; if (packageData != null) { packageData.forEach((key, value) { packageContent += '$key: $value\n'; print('Key: $key, Value: $value'); }); } return PackageCardDesign( packageName: filteredTests[index].name, package: packageContent, // 传入处理后的package内容 price: '${filteredTests[index].price} YR', details: filteredTests[index].details.toLowerCase(), colour: selectedColour(index), icon: Icons.ac_unit_outlined, type: filteredTests[index].type, ); }
内容的提问来源于stack exchange,提问作者Fada
相关产品推荐
相关产品推荐

