升级Cloud Firestore依赖后出现Object类型未定义[]操作符错误如何解决
报错原因
cloud_firestore 0.14.0及之后的版本引入了类型安全变更,DocumentSnapshot.data()和QueryDocumentSnapshot.data()方法的返回值从原来的Map<String, dynamic>调整为Object?类型,Dart无法直接对Object类型使用[]下标运算符访问属性,因此触发报错。
修复方案
最简单的修复方式是显式将data()返回的结果强制转换为Map<String, dynamic>类型,各文件修改后的代码如下:
model.dart 修复代码
Product.fromSnapshot(DocumentSnapshot snapshot){ // 先将返回数据转换为Map类型 final data = snapshot.data() as Map<String, dynamic>; _featured = data[FEATURED]; _brand = data[BRAND]; _category = data[CATEGORY]; }
update.dart 修复代码
FutureBuilder<QuerySnapshot>( future: FirebaseFirestore.instance .collection("items") .where("shortInfo", whereIn: (snapshots.data.docs[index].data() as Map<String, dynamic>)[EcommerceApp.productID]) .get(), builder: (c,snap) { if(!snap.hasData) return Center(child: circularProgress()); // 提前转换当前订单数据为Map,避免重复强转 final orderData = snapshots.data.docs[index].data() as Map<String, dynamic>; return AdminOrderCard( itemCount: snap.data!.docs.length, data:snap.data!.docs, orderId: snapshots.data.docs[index].id, orderBy: orderData["orderBy"], addressID: orderData["addressID"], ); }, ); List<DropdownMenuItem<String>> getCategoriesDropdown(){ List<DropdownMenuItem<String>> items = []; for(int i = 0; i < categories.length; i++){ setState(() { print(i); final catData = categories[i].data() as Map<String, dynamic>; items.insert(0, DropdownMenuItem(child: Text(catData['category']), value: catData['category'])); }); } return items; } _currentCategory = (categories[0].data() as Map<String, dynamic>)['category'];
pro.dart 修复代码
Future<void> getMobileandTabIconData() async { List<CategoryIcon> newList = []; QuerySnapshot dressSnapShot = await FirebaseFirestore.instance .collection("categoryicon") .doc("MhZyArOf2zrOmPO7R3y6") .collection("mobile&tablets") .get(); for (var element in dressSnapShot.docs) { final iconData = element.data() as Map<String, dynamic>; mobileandtabiconData = CategoryIcon(image: iconData["image"]); newList.add(mobileandtabiconData); } mobileandtabIcon = newList; notifyListeners(); }
可选优化方案
如果不想每次调用data()都手动强转,可以在查询时通过withConverter提前指定数据类型,示例如下:
final productRef = FirebaseFirestore.instance .collection("products") .withConverter<Map<String, dynamic>>( fromFirestore: (snapshot, _) => snapshot.data()!, toFirestore: (data, _) => data, );
后续通过这个引用查询得到的文档,data()返回值直接为Map<String, dynamic>类型,无需再次强转。
注意事项
如果担心数据为空或类型不匹配,可以用as?替代as并配合默认值避免崩溃,示例:
final data = snapshot.data() as Map<String, dynamic>?; _featured = data?[FEATURED] ?? false;
内容的提问来源于stack exchange,提问作者Aakib Algohar
相关产品推荐
相关产品推荐

