Flutter中Dio 5.4.3+1无法捕获错误问题(GetX场景)
解决Flutter GetX+Dio请求错误无法捕获的问题
问题根源
你的代码无法捕获错误的核心原因有两个:
await DioService().getMethod(url)执行在try代码块之外,Dio请求抛出的错误根本没进入捕获逻辑- DioService的
getMethod仅用then处理成功响应,未处理请求失败的情况,错误会直接向上抛出但上层未包裹捕获
另外错误处理逻辑存在嵌套错误:把connectionError判断放在401的分支里,而连接错误时e.response为null,永远不会触发这个提示。
修复步骤
1. 调整请求调用位置,包裹完整请求流程到try块
将Dio请求的调用移到try内部,确保所有请求相关的错误都能被捕获。
2. 优化DioService的getMethod实现
去掉冗余的then,直接返回Dio请求的Future,让上层统一处理错误;也可以在内部添加基础错误捕获,但建议上层处理业务相关错误。
3. 修正错误处理逻辑
区分不同类型的Dio错误:
- 有响应的错误(如401、404等):通过
e.response?.statusCode判断 - 无响应的错误(如连接失败、超时等):通过
e.type判断
4. 规范isLoading状态管理
请求开始时立即设置isLoading为true,成功或失败后同步设置为false,避免延迟导致的状态不一致。
修正后的完整代码
JemaatController 修正版
class JemaatController extends GetxController { RxList<JemaatJSON> jemaat = RxList(); RxBool isListViewScrollToTheDown = false.obs; RxBool isLoading = true.obs; RxBool isInternetConnect = true.obs; final deviceStorage = GetStorage(); var url = "${ConfigBack.apiAdress}/admin/jemaat/"; var itemController = ItemScrollController(); getJemaat() async { isLoading.value = true; // 请求开始立即设为加载中 try { var response = await DioService().getMethod(url); if (response.statusCode == 200) { jemaat.clear(); // 先清空旧数据再添加新数据 response.data.forEach((element) { jemaat.add(JemaatJSON.fromJson(element)); }); } } catch (e) { isInternetConnect.value = false; if (e is DioException) { // 处理无响应的连接类错误 if (e.type == DioExceptionType.connectionError || e.type == DioExceptionType.connectionTimeout || e.type == DioExceptionType.receiveTimeout) { FilemonHelperFunctions.showSnackBar( "Koneksi bermasalah, ini bukan pada perangkat anda"); } // 处理有响应的状态码错误 else if (e.response?.statusCode == 401) { FilemonHelperFunctions.showSnackBar( "Waktu sesi telah berakhir silahkan Re-Log"); deviceStorage.write('user_login', false); deviceStorage.write('IsFirstTime', false); deviceStorage.remove('usertoken'); deviceStorage.remove('userC'); NavigationAdmin().toMain(); } // 其他有响应的错误 else { FilemonHelperFunctions.showSnackBar( "Error: ${e.response?.statusMessage ?? 'Unknown error'}"); } } else { // 非Dio错误 FilemonHelperFunctions.showSnackBar("Terjadi kesalahan: $e"); } } finally { // 无论成功失败,最终都关闭加载状态 isLoading.value = false; } } remJemaat() async { jemaat.clear(); } scrollListViewDownward() { itemController.scrollTo( index: jemaat.length - 4, duration: const Duration(seconds: 2), curve: Curves.fastOutSlowIn); isListViewScrollToTheDown.value = true; } scrollListViewUpward() { itemController.scrollTo( index: 0, duration: const Duration(seconds: 2), curve: Curves.fastOutSlowIn); isListViewScrollToTheDown.value = false; } @override void onInit() { getJemaat(); super.onInit(); } }
DioService 修正版
class DioService { Future<dynamic> getMethod(String url) async { dioUpers.Dio dio = dioUpers.Dio(); dioUpers.Options options = dioUpers.Options(headers: HeadersCode().data(), method: "GET"); // 直接返回请求Future,让上层处理错误 return await dio.get(url, options: options); } }
关键说明
- 使用
finally块确保isLoading一定会被设置为false,避免请求失败时状态卡住 - 拆分错误处理逻辑,分别处理连接类错误和状态码错误,避免逻辑嵌套错误
- 请求开始时立即设置加载状态,提升用户体验
- 清空旧数据再添加新数据,避免列表数据重复
内容的提问来源于stack exchange,提问作者Filemon Sitanggang
相关产品推荐
相关产品推荐

