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

为何catch代码块未进一步重新抛出错误?(Flutter场景)

问题分析:类型转换错误未被正确处理的原因

问题描述

从数据库提取数据时,无可用数据时extrectedData变量返回null,触发type 'Null' is not a subtype of type 'Map<String, dynamic>'类型转换错误。虽然catch块打印了"error Occured",但错误仍以未处理异常抛出,请问问题出在哪里?

相关代码

try {
      final response = await http.get(Uri.parse(url1));
      final extrectedData = json.decode(response.body);
      // print(extrectedData);
      final List<Product> lodedProducts = [];

      var url =
          "https://my-shop-1af19-default-rtdb.firebaseio.com/isFavorite/$userId.json?auth=$authToken";

      final favoriteResponse = await http.get(Uri.parse(url));
      final favoriteData = json.decode(favoriteResponse.body);

      (extrectedData as Map<String, dynamic>).forEach((prodId, prodData) {
        lodedProducts.add(
          Product(
            id: prodId,
            title: prodData['title'],
            description: prodData['description'],
            price: prodData['price'],
            imageUrl: prodData['imageUrl'],
            isFavorite:
                favoriteData == null ? false : favoriteData[prodId] ?? false,
          ),
        );
        _items = lodedProducts;
        notifyListeners();
      });
    } catch (error) {
      print('error Occured');
      // print(error.toString());
      rethrow;
    }

报错输出

I/flutter ( 7560): error Occured
E/flutter ( 7560): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast
E/flutter ( 7560): #0      Products.fetchAndSetProducts
products.dart:85
E/flutter ( 7560): <asynchronous suspension>
E/flutter ( 7560):

问题根源

  1. 强制类型转换触发错误:当extrectedData为null时,(extrectedData as Map<String, dynamic>)的强制类型转换会抛出CastError,这是Dart中的Error类型错误。
  2. catch块捕获后重新抛出:你的catch块确实捕获到了错误(因此打印了"error Occured"),但随后执行了rethrow语句将错误重新抛出。如果调用fetchAndSetProducts的上层代码没有额外的try/catch逻辑,这个错误就会变成未处理异常。
  3. 核心疏漏:未提前处理null场景:最根本的问题是没有在类型转换前判断extrectedData是否为null,直接执行强制转换导致错误发生。

解决办法

方法一:提前判断null,规避类型转换错误

在执行类型转换前先检查数据是否为null,无数据时直接处理空状态:

try {
  final response = await http.get(Uri.parse(url1));
  final extrectedData = json.decode(response.body);
  final List<Product> lodedProducts = [];

  var url =
      "https://my-shop-1af19-default-rtdb.firebaseio.com/isFavorite/$userId.json?auth=$authToken";

  final favoriteResponse = await http.get(Uri.parse(url));
  final favoriteData = json.decode(favoriteResponse.body);

  // 新增null判断,避免类型转换错误
  if (extrectedData != null) {
    (extrectedData as Map<String, dynamic>).forEach((prodId, prodData) {
      lodedProducts.add(
        Product(
          id: prodId,
          title: prodData['title'],
          description: prodData['description'],
          price: prodData['price'],
          imageUrl: prodData['imageUrl'],
          isFavorite:
              favoriteData == null ? false : favoriteData[prodId] ?? false,
        ),
      );
    });
  }
  // 无论有无数据,都更新状态
  _items = lodedProducts;
  notifyListeners();
} catch (error) {
  print('error Occured: ${error.toString()}');
  // 若不需要上层处理,移除rethrow;若需要,确保上层有捕获逻辑
  // rethrow;
}

方法二:使用安全类型转换as?

用as?替代as,转换失败时返回null,避免抛出错误:

final dataMap = extrectedData as? Map<String, dynamic>;
if (dataMap != null) {
  dataMap.forEach((prodId, prodData) {
    // 原逻辑代码
  });
}

方法三:控制错误的传递逻辑

  • 如果不需要上层感知错误,直接删除rethrow语句,错误会在当前catch块终止。
  • 如果需要上层处理错误,必须在调用fetchAndSetProducts的地方添加try/catch:
// 上层调用示例
try {
  await products.fetchAndSetProducts();
} catch (e) {
  // 这里处理错误逻辑
}

内容的提问来源于stack exchange,提问作者Smit Prajapati

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:05:57