使用StreamBuilder从Firestore取数时触发空检查运算符错误
解决Cloud Firestore StreamBuilder获取数据时的“Null check operator used on a null value”错误
核心问题分析
你遇到的空值错误,主要是Firestore字段名与模型类的字段映射不匹配,加上代码中过度使用非空断言符!导致的:
- 你的Firestore数据字段(如
phone number、image、tax options),和模型fromJson方法里使用的键(如phoneNo、storeImage、taxValue)完全不对应,导致从JSON中取出的值为null,再用!强制非空就触发了崩溃。 - 代码中多处直接使用
!断言非空(如snapshot.data!.data()!、_auth.currentUser!.uid),没有处理空值场景。
具体修复步骤
1. 修正模型类的fromJson字段映射
把fromJson里的键改成和Firestore数据完全一致的名称,同时移除不必要的非空断言:
class VendorUserModels{ final bool? approved; final String? businessName; final String? cityValue; final String? countryValue; final String? email; final String? phoneNo; final String? stateValue; final String? storeImage; final String? taxNumber; final String? taxValue; // 去掉可空字段的required修饰符,允许传入null VendorUserModels({ this.approved, this.businessName, this.cityValue, this.countryValue, this.email, this.phoneNo, this.stateValue, this.storeImage, this.taxNumber, this.taxValue }); // 修正字段映射,匹配Firestore的实际键名 VendorUserModels.fromJson(Map<String, Object?> json): this( approved: json['approved'] as bool?, businessName: json['businessName'] as String?, cityValue: json['city'] as String?, // 对应Firestore的city字段 countryValue: json['country'] as String?, // 对应Firestore的country字段 email: json['email'] as String?, phoneNo: json['phone number'] as String?, // 对应Firestore的phone number字段 stateValue: json['state'] as String?, // 对应Firestore的state字段 storeImage: json['image'] as String?, // 对应Firestore的image字段 taxNumber: json['tax number'] as String?, // 对应Firestore的tax number字段 taxValue: json['tax options'] as String?, // 对应Firestore的tax options字段 ); Map<String, Object?>toJson(){ return{ 'businessName': businessName, 'email':email, 'phone number': phoneNo, 'country': countryValue, 'state':stateValue, 'city': cityValue, 'tax options': taxValue, 'tax number': taxNumber, 'image': storeImage, 'approved':approved }; } }
2. 优化StreamBuilder的空值安全处理
在StreamBuilder中增加空值判断,避免直接使用!断言:
class LandingScreen extends StatelessWidget { const LandingScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final FirebaseAuth _auth = FirebaseAuth.instance; final CollectionReference _vendorsStream = FirebaseFirestore.instance.collection('vendors'); // 先判断用户是否登录 final user = _auth.currentUser; if (user == null) { return const Scaffold(body: Text("请先登录")); } return Scaffold( body: StreamBuilder<DocumentSnapshot>( stream: _vendorsStream.doc(user.uid).snapshots(), builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) { if (snapshot.hasError) { return const Text('加载出错'); } if (snapshot.connectionState == ConnectionState.waiting) { return const Text("加载中"); } // 判断文档是否存在、数据是否非空 if (!snapshot.data!.exists) { return const Text("用户数据不存在"); } final data = snapshot.data!.data() as Map<String, dynamic>?; if (data == null) { return const Text("无有效数据"); } VendorUserModels _vendorUserModel = VendorUserModels.fromJson(data); return Text(_vendorUserModel.businessName ?? "未设置商家名称"); } ) ); } }
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

