Flutter空安全报错:无法无条件调用[]方法,接收者可为null
解决Dart空安全报错:The method '[]' can't be unconditionally invoked because the receiver can be 'null'
问题根源
你的Trips和Vehicle模型类所有字段都是非空的required String,但从Firestore获取的doc.data()或snapshot.data()返回可空类型,用?[]取到的值同样可空,无法直接赋值给非空字段,触发空安全报错;同时getVehicle方法里存在snapshot.data的用法错误,正确获取数据的方法是data()。
具体修复方案
1. 修复getTrips方法
根据Firestore字段的实际存在情况,选择以下方案:
- 确认字段必存在时:用
!断言(仅在确保字段不会为空时使用)
Stream<List<Trips>> getTrips() { return _firestore .collection('trips') .snapshots() .map((snapshot) => snapshot.docs .map((doc) => Trips( id: doc.id, departure: doc.data()!['departure'], destination: doc.data()!['destination'], vehicleID: doc.data()!['vehicleID'], )) .toList()); }
- 字段可能为空时:要么修改模型字段为可空,要么提供默认值
// 方案A:修改Trips模型为可空字段 class Trips { final String id; final String? departure; final String? destination; final String? vehicleID; Trips({required this.id, this.departure, this.destination, this.vehicleID}); } // 方案B:保留非空字段,给空值设默认值 Stream<List<Trips>> getTrips() { return _firestore .collection('trips') .snapshots() .map((snapshot) => snapshot.docs .map((doc) => Trips( id: doc.id, departure: doc.data()?['departure'] ?? '默认出发地', destination: doc.data()?['destination'] ?? '默认目的地', vehicleID: doc.data()?['vehicleID'] ?? '默认车辆ID', )) .toList()); }
2. 修复getVehicle方法
先修正数据获取的错误写法,再处理空值:
Future<Vehicle> getVehicle(String id) async { DocumentSnapshot snapshot = await _firestore.collection('vehicle').doc(id).get(); final data = snapshot.data() as Map<String, dynamic>?; return Vehicle( id: snapshot.id, // 选择1:断言字段必存在(确保Firestore文档有这些字段时用) Driver: data!['Driver'], name: data!['name'], type: data!['type'], // 选择2:给空值设默认值 // Driver: data?['Driver'] ?? '默认司机', // name: data?['name'] ?? '默认车辆名', // type: data?['type'] ?? '默认车型', ); }
若允许车辆字段为空,修改Vehicle模型:
class Vehicle { final String id; final String? Driver; final String? name; final String? type; Vehicle({required this.id, this.Driver, this.name, this.type}); }
3. 严谨写法(推荐)
过滤掉缺少必要字段的文档,避免潜在崩溃:
Stream<List<Trips>> getTrips() { return _firestore .collection('trips') .snapshots() .map((snapshot) => snapshot.docs .where((doc) { final data = doc.data(); return data != null && data.containsKey('departure') && data.containsKey('destination') && data.containsKey('vehicleID'); }) .map((doc) => Trips( id: doc.id, departure: doc.data()!['departure'], destination: doc.data()!['destination'], vehicleID: doc.data()!['vehicleID'], )) .toList()); }
内容的提问来源于stack exchange,提问作者tis eyat
相关产品推荐
相关产品推荐

