Flutter访问Firebase Firestore缺失字段抛出异常如何处理?
Flutter Firestore 字段不存在异常解决方案
异常原因
Bad state: field does not exist within the DocumentSnapshotPlatform异常是因为 FirestoreDocumentSnapshot的[]取值运算符在目标字段不存在时会直接抛出异常,而非返回null,因此??空判断运算符无法生效(取值操作在空判断执行前就已经崩溃)。
你单独对字段取值加try catch仍然抛出未处理异常的原因是未覆盖所有字段取值逻辑,或未正确捕获异步回调内的异常。
解决方案
推荐两种安全取值的实现方式,均可实现字段不存在时自动返回null的需求:
方案1:先转成Map再取值(最便捷)
调用DocumentSnapshot的data()方法先把整个文档内容转为Map<String, dynamic>?类型,原生Map的key不存在时会直接返回null,无需额外异常捕获:
CollectionReference coursesRef = FirebaseFirestore.instance.collection('courses'); coursesRef .orderBy('users', descending: true) .limit(6) .get() .then((QuerySnapshot querySnapshot) { for (var doc in querySnapshot.docs) { // 先把文档转为Map Map<String, dynamic>? docData = doc.data() as Map<String, dynamic>?; courses.add( ModelCourse( authorUid: docData?['authorUid'], name: docData?['name'], courseInfo: docData?['courseInfo'], oldCost: docData?['oldCost'], newCost: docData?['newCost'], catName: docData?['catName'], language: docData?['language'], color: docData?['color'], reviews: null, path: null, ), ); } // 建议补充catch块捕获整个异步请求的异常 }).catchError((error) { print('请求课程数据失败: $error'); });
方案2:封装扩展方法(可复用场景)
如果需要在多处做安全取值,可以给DocumentSnapshot封装通用的安全取值扩展:
extension SafeDocumentSnapshot on DocumentSnapshot { T? get<T>(String field, [T? defaultValue]) { try { return get(field) as T?; } catch (e) { return defaultValue; } } }
封装后直接调用扩展方法取值即可:
ModelCourse( authorUid: doc.get('authorUid'), name: doc.get('name'), // 其余字段同理 )
注意事项
请确认ModelCourse的所有可选参数的类型声明都是可空类型(例如String? name而非String name),否则传入null时仍然会触发类型异常。
内容的提问来源于stack exchange,提问作者ulukbek
相关产品推荐
相关产品推荐

