Flutter从Firebase取数据报错NoSuchMethodError,求解决方案
问题:Firebase获取商品数据时触发NoSuchMethodError: The method '[]' was called on null
问题说明
从Firebase服务器拉取商品数据时,登录阶段出现错误:Unhandled Exception: NoSuchMethodError: The method '[]' was called on null。此前通过以下代码处理空值问题,但删除服务器上的用户收藏数据后错误复现,推测与空安全逻辑有关但无法自行修复:
bool? _isFavorite = favoriteData[key] != null || favoriteData[key] == 'true' ? true : false;
相关代码
Fetch Data 函数
Future<void> fetchAndSetProducts([bool filterByUser = false]) async { final filterString = filterByUser ? 'orderBy="creatorId"&equalTo="$userId"' : ''; var url = 'https://ecommerce-test-753ad-default-rtdb.firebaseio.com/products.json?auth=$authToken&$filterString'; try { final response = await http.get(Uri.parse(url)); final extractedData = json.decode(response.body) as Map<String, dynamic>; if (extractedData == {}) { return; } url = 'https://ecommerce-test-753ad-default-rtdb.firebaseio.com/userFavorites/$userId.json?auth=$authToken'; final favoriteResponse = await http.get(Uri.parse(url)); final favoriteData = json.decode(favoriteResponse.body); print(favoriteData); print(extractedData); final List<Product> loadedProduct = []; extractedData.forEach((key, value) { bool? _isFavorite = favoriteData[key] != null || favoriteData[key] == 'true' ? true : false; loadedProduct.add( Product( id: key, title: value['title'], price: value['price'], imageUrl: value['imageUrl'], description: value['description'], isFavorite: _isFavorite, ), ); }); _productItems = loadedProduct; notifyListeners(); } catch (e) { rethrow; } }
Product Model 类
class Product with ChangeNotifier { final String id; final String title; final double price; final String imageUrl; final String description; bool isFavorite; Product({ required this.id, required this.title, required this.price, required this.imageUrl, required this.description, this.isFavorite = false, }); void _setFavValue(bool newValue) { isFavorite = newValue; notifyListeners(); } Future<void> toggleFavoriteStatus(String authToken, String userId) async { final oldStatus = isFavorite; isFavorite = !isFavorite; notifyListeners(); final url = 'https://ecommerce-test-753ad-default-rtdb.firebaseio.com/userFavorites/$userId/$id.json?auth=$authToken'; try { final response = await http.put( Uri.parse(url), body: json.encode(isFavorite), ); if (response.statusCode >= 400) { _setFavValue(oldStatus); } } catch (error) { _setFavValue(oldStatus); } } }
Firebase 规则配置
"products":{ ".indexOn":["creatorId"] }
解决方案
错误核心原因:当服务器上的用户收藏数据被删除后,favoriteData本身会变为null,此时直接调用favoriteData[key]就会触发[]方法调用在null对象上的错误。同时原代码的逻辑判断存在漏洞(用||会导致favoriteData[key]为false时仍返回true)。
修复方案1:先判断favoriteData是否为null
修改_isFavorite的赋值逻辑:
bool _isFavorite = false; if (favoriteData != null) { final favValue = favoriteData[key]; _isFavorite = favValue == true || favValue == 'true'; }
修复方案2:使用Dart空安全语法简化判断
bool _isFavorite = (favoriteData?[key] == true || favoriteData?[key] == 'true') ?? false;
额外优化:提前处理favoriteData的null情况
在解析收藏数据时,直接给null情况赋值为空Map,避免后续所有判断都要处理null:
final favoriteData = json.decode(favoriteResponse.body) ?? <String, dynamic>{};
之后直接调用favoriteData[key]只会返回null,不会触发方法调用错误,再按正常逻辑判断即可。
内容的提问来源于stack exchange,提问作者Muhammad Tawil
相关产品推荐
相关产品推荐

