为何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):
问题根源
- 强制类型转换触发错误:当
extrectedData为null时,(extrectedData as Map<String, dynamic>)的强制类型转换会抛出CastError,这是Dart中的Error类型错误。 - catch块捕获后重新抛出:你的catch块确实捕获到了错误(因此打印了"error Occured"),但随后执行了
rethrow语句将错误重新抛出。如果调用fetchAndSetProducts的上层代码没有额外的try/catch逻辑,这个错误就会变成未处理异常。 - 核心疏漏:未提前处理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
相关产品推荐
相关产品推荐

