You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 18:28:01