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

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块
  }
}

验证步骤

  1. 确认Dio实例初始化时已添加AppInterceptors。
  2. 模拟网络异常(比如断网、调用无效接口),查看控制台是否打印拦截器的ERROR日志。
  3. 检查post方法的try-catch是否能捕获到DioError,并触发对应的异常抛出。

内容的提问来源于stack exchange,提问作者Amine Zeroual

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:05:33