Flutter中Firebase嵌套Map查询问题:修复fromSnapshot方法
Firebase嵌套Map数据模型fromSnapshot方法修复求助
我为Firebase的嵌套Map数据定义了如下模型,该模型可将嵌套Map数据正常上传至Firebase(数据结构见下方截图)。现在我希望从Firebase查询数据并通过ListViewBuilder在应用中展示,但查询时出现异常,请求帮助修复模型中的fromSnapshot方法。
原模型代码
class Names { UserInformationModelMap names; Names({ required this.names, }); Map<String, dynamic> toMap() { return <String, dynamic>{ 'names': names.toMap(), }; } factory Names.fromMap(Map<String, dynamic> map) { return Names( names: UserInformationModelMap.fromMap( map['names'] as Map<String, dynamic>, ), ); } factory Names.fromSnapshot(DocumentSnapshot<Map<String, dynamic>> doc) { return Names( names: UserInformationModelMap.fromSnapshot( doc, ), ); } } class UserInformationModelMap { WholeNameMap fullName; String? uid; UserInformationModelMap({ required this.fullName, this.uid, }); Map<String, dynamic> toMap() { return <String, dynamic>{ uid!: fullName.toMap(), }; } factory UserInformationModelMap.fromMap(Map<String, dynamic> map) { return UserInformationModelMap( fullName: WholeNameMap.fromMap(map['fullName'] as Map<String, dynamic>), ); } factory UserInformationModelMap.fromSnapshot( DocumentSnapshot<Map<String, dynamic>> doc) { return UserInformationModelMap( fullName: WholeNameMap.fromMap(doc['fullName'] as Map<String, dynamic>), ); } } class WholeNameMap { String firstName; String lastName; WholeNameMap({ required this.firstName, required this.lastName, }); Map<String, dynamic> toMap() { return <String, dynamic>{ 'firstName': firstName, 'lastName': lastName, }; } factory WholeNameMap.fromMap(Map<String, dynamic> map) { return WholeNameMap( firstName: map['firstName'] as String, lastName: map['lastName'] as String, ); } }
Firebase数据结构截图

查询异常截图

问题分析与修复方案
问题根源
异常Bad state: No element是因为模型的fromSnapshot方法没有正确匹配Firebase的嵌套结构:
Names.fromSnapshot错误地将整个文档快照直接传给UserInformationModelMap.fromSnapshot,但实际UserInformationModelMap对应的数据在文档的names字段下。UserInformationModelMap.fromMap和fromSnapshot试图直接从根节点取fullName,但实际fullName是嵌套在names字段下以uid为键的子Map中。
修正后的模型代码
class Names { UserInformationModelMap names; Names({ required this.names, }); Map<String, dynamic> toMap() { return <String, dynamic>{ 'names': names.toMap(), }; } factory Names.fromMap(Map<String, dynamic> map) { return Names( names: UserInformationModelMap.fromMap( map['names'] as Map<String, dynamic>, ), ); } factory Names.fromSnapshot(DocumentSnapshot<Map<String, dynamic>> doc) { final data = doc.data()!; return Names( names: UserInformationModelMap.fromMap(data['names'] as Map<String, dynamic>), ); } } class UserInformationModelMap { WholeNameMap fullName; String? uid; UserInformationModelMap({ required this.fullName, this.uid, }); Map<String, dynamic> toMap() { return <String, dynamic>{ uid!: fullName.toMap(), }; } factory UserInformationModelMap.fromMap(Map<String, dynamic> map) { // 从map中取出唯一的键作为uid,对应的值是fullName的Map final entry = map.entries.first; final uid = entry.key; final fullNameMap = entry.value as Map<String, dynamic>; return UserInformationModelMap( uid: uid, fullName: WholeNameMap.fromMap(fullNameMap), ); } // 基于fromMap实现fromSnapshot,保证逻辑一致性 factory UserInformationModelMap.fromSnapshot(DocumentSnapshot<Map<String, dynamic>> doc) { final data = doc.data()!; return UserInformationModelMap.fromMap(data['names'] as Map<String, dynamic>); } } class WholeNameMap { String firstName; String lastName; WholeNameMap({ required this.firstName, required this.lastName, }); Map<String, dynamic> toMap() { return <String, dynamic>{ 'firstName': firstName, 'lastName': lastName, }; } factory WholeNameMap.fromMap(Map<String, dynamic> map) { return WholeNameMap( firstName: map['firstName'] as String, lastName: map['lastName'] as String, ); } }
关键修改点
- Names.fromSnapshot:先获取文档数据,取出
names字段后再传给UserInformationModelMap.fromMap,而非直接传递整个快照。 - UserInformationModelMap.fromMap:遍历
names下的键值对(以uid为键),取出uid和对应的fullName子Map,正确解析嵌套结构。 - UserInformationModelMap.fromSnapshot:调整为基于
fromMap实现,保证逻辑一致性。
内容的提问来源于stack exchange,提问作者Tristaaaan
相关产品推荐
相关产品推荐

