Flutter中Dio包无法捕获DioError及拦截器onError未触发问题
问题分析与解决方案
核心问题排查
1. 拦截器未绑定到Dio实例
你的自定义AppInterceptors如果没添加到Dio的拦截器列表里,onError方法肯定不会被触发。检查Dio实例的初始化代码,必须加上这行:
final Dio client = Dio(); client.interceptors.add(AppInterceptors()); // 这一步不能少
2. DioError捕获失效的潜在原因
- 部分异常被“吞掉”:你的
_handleDioError方法里,connectTimeout、sendTimeout、cancel这些分支没有抛出异常,导致对应类型的DioError处理后直接消失,上层调用者感知不到。 - Dio版本与导入问题:Dio 4.x的
DioError结构有调整,确保导入的是官方包:
不要自行扩展import 'package:dio/dio.dart';DioError类,这会破坏原有异常体系,导致捕获失效。
代码修复建议
完善post方法的异常捕获逻辑
补充通用异常捕获,避免非DioError类型的异常漏处理:
@override Future post( String path, { Map<String, dynamic>? body, bool formDataIsEnabled = false, Map<String, dynamic>? queryParams, }) async { try { debugPrint("ENTERING THE POST METHOD:"); final response = await client.post(path, queryParameters: queryParams, data: formDataIsEnabled ? FormData.fromMap(body!) : body); return _handleJsonResponse(response); } on DioError catch (error) { return _handleDioError(error); } catch (e) { debugPrint('Unexpected error: $e'); throw ServerExceptions(message: "Unexpected error"); } }
补全_handleDioError的所有分支
确保每个DioErrorType都有明确的异常抛出,避免异常丢失:
dynamic _handleDioError(DioError error) { switch (error.type) { case DioErrorType.connectTimeout: throw FetchDataException(message: "连接超时"); case DioErrorType.sendTimeout: throw FetchDataException(message: "请求发送超时"); case DioErrorType.receiveTimeout: throw FetchDataException(); case DioErrorType.response: switch (error.response?.statusCode) { case StatusCode.badRequest: throw BadRequestException(); case StatusCode.unauthorized: case StatusCode.forbidden: throw UnauthorisedException(); case StatusCode.notFound: throw NotFoundException(); case StatusCode.conflict: throw ConflictException(); case StatusCode.internalServerError: throw InternalServerErrorException(); default: throw ServerExceptions(message: "未知响应错误"); } case DioErrorType.cancel: throw ServerExceptions(message: "请求已取消"); case DioErrorType.other: throw ServerExceptions(message: "网络异常,请检查网络连接"); } }
优化拦截器的方法实现
Dio 4.x中建议直接调用handler的方法替代super,确保异常能正常传递:
class AppInterceptors extends Interceptor { @override Future onRequest(RequestOptions options, RequestInterceptorHandler handler) async { debugPrint('REQUEST [${options.method}]=>PATH: ${options.path}'); options.headers[AppStrings.contentType] = AppStrings.applicationContentType; handler.next(options); } @override Future onResponse(Response response, ResponseInterceptorHandler handler) async { debugPrint('RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}'); handler.next(response); } @override Future onError(DioError err, ErrorInterceptorHandler handler) async { debugPrint('ERROR[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}'); handler.next(err); // 确保异常继续传递到post方法的catch块 } }
验证步骤
- 确认Dio实例初始化时已添加
AppInterceptors。 - 模拟网络异常(比如断网、调用无效接口),查看控制台是否打印拦截器的
ERROR日志。 - 检查post方法的try-catch是否能捕获到DioError,并触发对应的异常抛出。
内容的提问来源于stack exchange,提问作者Amine Zeroual
相关产品推荐
相关产品推荐

