位置:首页 > Dart > 系统化掌握Dart网络编程之Dio(四):拦截器篇

系统化掌握Dart网络编程之Dio(四):拦截器篇

时间:2026-08-27  |  作者:怪兽小助手  |  阅读:0

目录

  1. 前言
  2. 一、基本概念
  3. 1.1、本质定义
  4. 二、核心价值
  5. 2.1、统一处理: 解决代码重复性问题
  6. 2.2、职责分离:实现 网络层 与 业务逻辑 解耦( 高内聚低耦合 )
一、基本概念 对应的技术说明图
一、基本概念概括一、基本概念的核心概念、关键要点与实践提示。
前言 对应的技术说明图
前言概括前言的核心概念、关键要点与实践提示。

前言

在移动应用开发中,网络请求如同血管中的血液,承载着数据交互的生命力。然而,每个请求手动添加Token、全局处理错误码及统一添加埋点日志等重复性工作,不仅效率低下,更让代码臃肿难维护。Dio拦截器正是为解决这些问题而生的利器。它像一位隐形的网络请求调度员,在请求发出前、响应返回后甚至错误发生时,以流水线的方式对数据进行加工和拦截。本文将深入Dio拦截器的底层逻辑,通过系统化思维拆解其设计哲学,并展示如何构建高扩展性的网络层。

系统化掌握Dart网络编程之Dio(四):拦截器篇 的核心流程信息图
系统化掌握Dart网络编程之Dio(四):拦用简体中文信息图概括系统化掌握Dart网络编程之Dio(四):拦的核心流程、关键规则与实践要点。

前言

在移动应用开发中,网络请求如同血管中的血液,承载着数据交互的生命力。然而,你是否遇到过这样的场景:每个请求都要手动添加Token全局处理错误码统一添加埋点日志……这些重复性工作不仅效率低下,更让代码臃肿难维护。

Dio拦截器,正是为解决这些问题而生的利器。它像一位隐形的"网络请求调度员",在请求发出前响应返回后甚至错误发生时,以流水线的方式对数据进行加工和拦截。

本文将带你深入Dio拦截器的底层逻辑,通过系统化的思维拆解其设计哲学,并通过实战案例展示如何用它构建高扩展性的网络层。你是否准备好,让代码从此优雅起来?

千曲而后晓声,观千剑而后识器。虐它千百遍方能通晓其真意

一、基本概念

1.1、本质定义

拦截器Dio网络库提供的一种中间件机制,允许在网络请求的生命周期中请求发出前响应返回后错误发生时)插入自定义逻辑。

它通过链式处理模型,将多个独立的处理单元拦截器)按顺序串联,形成一个可扩展的流水线流程

深入理解
想象一家外卖配送中心:

  • 1、接单员onRequest)检查订单完整性。
  • 2、打包员添加餐具(添加请求头)。
  • 3、配送员onResponse)检查餐品是否完好。
  • 4、客服onError)处理配送异常 。

二、核心价值

2.1、统一处理:解决代码重复性问题

问题场景
在未使用拦截器时,开发者需要在每个网络请求中手动处理以下逻辑:

  • 添加认证Token
  • 解析业务状态码(如接口返回的code字段)。
  • 记录请求日志
  • 错误重试Token刷新

代码反例

// 每个请求都需重复相同逻辑
Future fetchData() async {
  try {
    final response = await dio.get(
      '/api/user',
      options: Options(headers: {'Authorization': 'Bearer $token'}), // 手动添加Token
    );
    // 手动解析业务状态码
    if (response.data['code'] != 200) {
      throw AppException(response.data['message']);
    }
    return User.fromJson(response.data);
  } on DioException catch (e) {
    // 手动处理错误
    if (e.response.statusCode == 401) {
      await refreshToken();
      return fetchData(); // 重试请求
    }
    rethrow;
  }
}

拦截器价值

通过拦截器,上述分散在各处的重复代码被集中管理。开发者只需在拦截器中定义一次处理逻辑,即可对所有网络请求生效。这不仅大幅减少了代码冗余,还显著提升了代码的可维护性和可读性。当业务规则发生变化时,只需修改拦截器中的逻辑,无需逐个修改每个网络请求的代码,从而降低了维护成本并减少了出错概率。

此外,拦截器提供了一种标准化的错误处理机制。无论是网络超时、服务器错误还是业务逻辑错误,都可以通过统一的拦截器进行捕获和处理,确保应用在面对异常时能够做出一致且合理的响应,提升用户体验和系统的稳定性。

最后,拦截器还支持灵活的配置和扩展。开发者可以根据项目需求,轻松添加、移除或调整拦截器的顺序,以适应不同的业务场景和技术要求。这种灵活性使得拦截器成为现代网络编程中不可或缺的重要组件。

2.2、职责分离:实现网络层业务逻辑解耦(高内聚低耦合

问题场景
网络层逻辑(如加密算法缓存策略)直接嵌入业务代码时:

  • 业务代码臃肿,可读性下降。
  • 修改网络逻辑需全局搜索替换,容易引入错误
  • 不同模块可能实现不一致的网络处理逻辑。

通过拦截器,可以将网络层的关注点分解为独立模块:

  • 横向分层
    • 基础层日志加密)、业务层Token刷新错误提示)、监控层性能统计)。
  • 纵向隔离
    • 不同模块的拦截器互不干扰,例如日志拦截器无需感知加密逻辑 。

无拦截器方案

// 无拦截器:业务代码中混杂网络逻辑
Future fetchUser() async {
  try {
    // 手动添加Token
    final response = await dio.get('/user', options: Options(
      headers: {'Authorization': 'Bearer $token'},
    ));
    // 手动解析业务状态码
    if (response.data['code'] != 200) {
      throw CustomError(response.data['message']);
    }
    return User.fromJson(response.data);
  } on DioException catch (e) {
    // 手动处理错误
    showErrorDialog(e.message);
  }
}

拦截器方案

// 业务代码
Future fetchData() async {
  return dio.get('/api/user').then((res) => User.fromJson(res.data));
}

// 网络层独立模块
dio.interceptors.addAll([
  AuthInterceptor(),    // 认证
  LoggingInterceptor(), // 日志
  RetryInterceptor(),   // 重试
  BizCodeInterceptor(), // 业务状态码解析
]);

核心优势

  • 业务代码纯粹:仅关注数据转换,不涉及网络细节
  • 网络层可独立演进:修改加密算法缓存策略时,无需改动业务代码。

2.3、动态扩展:灵活调整请求流程

核心能力
拦截器支持在运行时动态添加或移除,无需修改业务代码即可调整网络层行为,实现“热插拔”式的功能扩展。

典型场景
①、环境切换

// 开发环境:添加日志拦截器  
if (isDev) dio.interceptors.add(LogInterceptor());  

// 生产环境:移除日志,添加加密拦截器  
if (isProd) {
  dio.interceptors.removeWhere((i) => i is LogInterceptor);
  dio.interceptors.add(EncryptInterceptor());
}

②、功能开关

三、核心方法详解

3.1、核心类详解

①、Interceptor:基类

所有自定义拦截器需继承自 Interceptor,其核心生命周期方法:

abstract class Interceptor {  
  void onRequest(RequestOptions options, RequestInterceptorHandler handler);  
  void onResponse(Response response, ResponseInterceptorHandler handler);  
  void onError(DioException err, ErrorInterceptorHandler handler);  
}  

②、RequestInterceptorHandlerResponseInterceptorHandlerErrorInterceptorHandler:控制类

用于控制拦截器链的传递流程,核心方法:

class RequestInterceptorHandler extends _BaseHandler {
  void next(RequestOptions requestOptions) {
  //...
  }

  void resolve(Response response, [bool callFollowingResponseInterceptor = false,]) {
  //...
  }

  void reject(DioException error, [
    bool callFollowingErrorInterceptor = false,]) {
    //...
  }
}

class ResponseInterceptorHandler extends _BaseHandler {
  
  void next(Response response) {
    //...
  }

  void resolve(Response response) {
    //...
  }

  void reject(DioException error, [
    bool callFollowingErrorInterceptor = false,]) {
    //...
  }
}

class ErrorInterceptorHandler extends _BaseHandler {

  void next(DioException error) {
    //...
  }

  void resolve(Response response) {
   //...
  }
  
  void reject(DioException error) {
   //...
  }
}

③、QueuedInterceptor:队列拦截器

顺序执行拦截器,适用于需要严格顺序的场景(如Token刷新)。


3.2、方法参数详解

①、onRequest 方法

该方法负责处理请求前的预处理逻辑,是拦截器介入网络通信的第一道关卡。开发者在此阶段可以获取并修改 RequestOptions 对象,从而动态调整请求头、查询参数或请求体数据。例如,在发送请求前自动注入认证 Token 或添加设备标识信息,确保服务端能够正确识别客户端身份。此方法通常返回一个 onResponse 类型的对象,若处理过程中发生异常,可直接抛出 Response 以中断后续流程,避免无效请求发送到服务器。通过精确控制此方法的执行逻辑,开发者能够实现细粒度的请求定制,提升网络交互的安全性与灵活性。

②、onError 方法

该方法用于处理来自服务器的响应数据,是拦截器介入网络通信的第二道关卡。在请求成功返回后,拦截器可以在此阶段对 DioException 对象进行解析或转换。常见的应用场景包括统一处理业务状态码、将原始 JSON 数据映射为特定的业务模型,或记录详细的响应日志。若响应数据不符合预期格式,拦截器可在此处进行数据清洗或格式修正,确保上层业务代码接收到的是标准化数据。此外,该方法还支持对响应头信息的读取,便于实现基于缓存策略的本地数据持久化逻辑。通过合理实现此方法,开发者可以屏蔽底层网络协议的复杂性,为业务层提供简洁、一致的数据接口。

③、handler.resolve() 方法

该方法专门用于处理网络请求过程中发生的异常,是拦截器介入网络通信的第三道关卡。当请求因网络超时、服务器错误(如 5xx 状态码)或客户端配置错误而失败时,此方法将被触发。开发者在此阶段可以捕获具体的 handler.reject() 类型异常,并根据错误类型执行相应的恢复策略。例如,对于网络不可用的情况,可以提示用户检查网络连接;对于认证失效的情况,可以自动刷新 Token 并重试请求。通过集中处理异常,拦截器能够统一错误提示风格,避免在业务代码中分散处理各种边界情况,从而提升应用的健壮性和用户体验。此外,该方法还支持记录详细的错误堆栈信息,便于开发人员进行问题排查和系统监控。

3.3、高级控制技巧

①、中断链式传递

在任意阶段调用 handler.resolve()handler.reject() 可提前终止拦截器链:

void onRequest(options, handler) {  
  if (无网络连接) {  
    // 直接返回自定义错误  
    handler.reject(DioException(  
      requestOptions: options,  
      error: '网络不可用',  
    ));  
  } else {  
    handler.next(options);  
  }  
}  

②、跨拦截器数据传递

通过 options.extra 字段在不同拦截器间共享数据:

// 拦截器A  
void onRequest(options, handler) {  
  options.extra['startTime'] = DateTime.now();  
  handler.next(options);  
}  

// 拦截器B  
void onResponse(response, handler) {  
  final duration = DateTime.now().difference(  
    response.requestOptions.extra['startTime']  
  );  
  print('请求耗时:$duration');  
  handler.next(response);  
}  

③、并发控制(QueuedInterceptorsWrapper

使用队列拦截器确保异步操作顺序执行:

dio.interceptors.add(QueuedInterceptorsWrapper(  
  onRequest: (options, handler) async {  
    // 确保同一时间只有一个请求进入  
    await _semaphore.acquire();  
    handler.next(options);  
    _semaphore.release();  
  },  
));  

3.4、方法调用全流程

①、请求阶段

请求发起 → 拦截器1.onRequest → 拦截器2.onRequest → ... → 发送网络请求  

②、响应阶段

收到响应 → 最后一个拦截器.onResponse → ... → 拦截器1.onResponse → 返回结果  

③、错误阶段

发生错误 → 最后一个拦截器.onError → ... → 拦截器1.onError → 抛出异常  

关键原则

  • 拦截器按注册顺序执行,错误处理需覆盖所有异常路径。
  • 避免在拦截器中进行耗时操作,以免阻塞主线程。
  • 合理使用 handler.resolve() 控制流程,防止无限循环。
  • 利用 options.extra 实现模块间数据解耦与共享。

四、实现原理

4.1、拦截器类型与生命周期

拦截器分为三类

  • 1、请求拦截器:在发送请求前修改请求参数(如添加 Headers加密数据)。
  • 2、响应拦截器:在收到响应后处理数据(如解析 JSON缓存结果)。
  • 3、错误拦截器:统一处理请求过程中的异常(如 Token 过期、网络错误)。

生命周期顺序为:

请求拦截器 → 发送请求 → 响应拦截器 → 错误拦截器(如发生异常)

4.2、责任链模式的实现

拦截器通过 递归调用__LAS_PROTECTED_130 对象 形成责任链。每个拦截器接收一个 __LAS_PROTECTED_131 参数,决定是否继续传递请求或直接返回。

  • 关键对象Handler

  • 执行流程

    • 创建一个初始 handler,指向实际发送 __LAS_PROTECTED_134 请求的逻辑。
    • 从最后一个拦截器开始,逆序 包裹每个拦截器的逻辑,形成链式调用。

4.3、拦截器接口

拦截器接口定义了三个主要的方法:

4.3、拦截器生命周期

在 Dio 中,拦截器的执行遵循严格的生命周期,主要包含三个关键阶段。开发者可以通过实现特定的回调方法来定义自定义的拦截器逻辑,从而在请求的不同阶段介入处理。

  • onRequest:在请求被发送之前被调用。这是处理请求参数、添加认证头或修改 URL 的最佳时机。
  • onResponse:在接收到服务器响应后被调用。此时可以对响应数据进行转换、解密或提取特定字段。
  • onError:在请求发生错误或异常时被调用。这是进行错误统一处理、重试机制或日志记录的关键环节。

通过合理实现这些方法,可以构建出强大且灵活的拦截器,以应对复杂的网络编程需求。

abstract class Interceptor {
  Future onRequest(RequestOptions options, RequestInterceptorHandler handler);
  Future onResponse(Response response, ResponseInterceptorHandler handler);
  Future<void> onError(DioError err, ErrorInterceptorHandler handler);
}

4.4、拦截器处理器

拦截器处理器(InterceptorHandler)允许拦截器在拦截过程中控制请求/响应的流程。它提供了两个主要的方法,用于决定拦截器的行为走向:

  • resolve:用于解决当前拦截器的问题,并继续后续流程。调用此方法后,请求或响应将继续传递给链中的下一个拦截器。
  • reject:用于拒绝当前的请求或响应,并中断后续流程。调用此方法后,将直接返回结果或抛出异常,不再执行后续的拦截器。

正确理解和使用这两个方法,是掌握拦截器流程控制的核心。

class RequestInterceptorHandler {
  Future resolve(RequestOptions options);
  Future<void> reject(error, StackTrace stackTrace]);
}

class ResponseInterceptorHandler {
  Future resolve(Response response);
  Future<void> reject(error, StackTrace stackTrace]);
}

class ErrorInterceptorHandler {
  Future<void> resolve(Response response);
  Future<void> reject(error, StackTrace stackTrace]);
}

4.5、拦截器链

Dio 实例维护了一个拦截器链,当请求发送或响应接收时,会依次调用链中的每个拦截器。拦截器链支持同步和异步拦截器,允许在拦截过程中进行复杂的异步操作,如数据转换或状态检查。

执行流程如下:

  • 请求发送前,依次调用每个拦截器的 onRequest 方法。此时可以修改请求配置。
  • 如果所有拦截器都通过(即调用 handler.resolve),则发送实际的 HTTP 请求。
  • 请求发送后,接收响应,依次调用每个拦截器的 onResponse 方法。此时可以处理响应数据。

如果在请求发送前或响应接收后发生错误,则依次调用每个拦截器的 onError 方法,以便进行统一的错误处理。


4.6、拦截器添加与管理

可以通过 dio.interceptors.add() 方法将自定义拦截器添加到拦截器链中。此外,Dio 还提供了一些内置的拦截器,如 LogInterceptor 用于自动记录请求和响应的日志,方便开发者调试和监控网络状态。

五、设计哲学

5.1、单一职责原则(SRP):精准的功能划分

每个拦截器仅处理 单一类型 的业务逻辑,避免功能耦合,确保代码可维护性复用性

在拦截器基类 Interceptor 中,通过分离 onRequestonResponseonError 方法,强制开发者按职责拆分逻辑:

关键点

  • 每个方法仅处理对应阶段的逻辑(如 onRequest 仅处理请求前操作)。
  • 开发者无法在一个方法中同时操作请求和响应,天然约束单一职责

5.2、开闭原则(OCP):无侵入式扩展

通过新增拦截器 而非修改已有代码来扩展功能,确保核心流程的稳定性

5.3、可插拔性:动态功能组合

通过 add/remove 方法,可在运行时动态调整拦截器,实现功能模块的热插拔。

关键点

  • 动态调整拦截器链不影响已发起的请求,仅作用于后续请求
  • 通过组合不同拦截器,可快速构建定制化网络层(如调试模式安全模式)。

5.4、设计优势总结

Dio 拦截器架构通过严格的职责分离与扩展机制,实现了高内聚低耦合。其核心优势在于:单一职责确保了逻辑清晰,开闭原则保障了系统稳定,而可插拔性则赋予了极高的灵活性。这种设计使得开发者能够以最小成本应对复杂多变的网络需求,同时保持代码库的整洁与高效。

六、总结

拦截器的核心价值与架构思维

拦截器的强大之处,在于将离散的网络处理逻辑转化为可编排的管道操作。通过理解其责任链模式的内核,我们能像搭积木一样构建高可维护的网络层:

  • 1、分层设计:基础拦截器处理通用逻辑(如日志),业务拦截器处理领域需求(如Token刷新)。
  • 2、流程控制:通过handler.next()resolve()reject()精确控制执行流。
  • 3、系统化思维:将网络层视为由独立模块组成的生态系统,而非一坨面条代码。

当你能游刃有余地使用拦截器编排请求生命周期时,那些曾经让你头疼的全局状态管理多环境适配问题,都将迎刃而解。优秀的架构不是设计出来的,而是通过拦截器这样的基础组件,逐步演化出来的

欢迎一键四连关注 + 点赞 + 收藏 + 评论

阶段方法触发时机典型操作
请求前处理onRequest请求即将发送到服务器之前修改请求头、添加公共参数、加密请求体
响应后处理onResponse服务器返回响应且HTTP状态码为2xx解析业务数据、转换数据结构、缓存响应结果
错误处理onError请求失败或HTTP状态码非2xx统一错误提示、重试机制、刷新Token
// 请求 -> 拦截器A的onRequest -> 拦截器B的onRequest -> 发送请求  
// 响应 -> 拦截器B的onResponse -> 拦截器A的onResponse -> 返回结果
dio.interceptors.add(InterceptorA()); // 先执行
dio.interceptors.add(InterceptorB()); // 后执行
onRequest: (options, handler) {
  if (无网络连接) {
    handler.reject(DioException(message: '网络不可用')); // 终止请求
  } else {
    handler.next(options); // 继续传递
  }
}
职责类型具体场景代码示例
数据加工添加全局请求头、参数加密、数据序列化options.headers['Authorization'] = 'Bearer $token'
流程控制重试失败请求、等待Token刷新后继续handler.retry(request)
监控与统计记录请求耗时、上报接口成功率log('API耗时:${DateTime.now().difference(startTime)}')
异常处理统一错误码映射、弹窗提示、降级处理if (error.response.statusCode == 504) showTimeoutDialog()
// 根据用户设置动态启用/禁用埋点  
analyticsEnabled  dio.interceptors.add(AnalyticsInterceptor()) 
                : dio.interceptors.remove(AnalyticsInterceptor());
// 特定页面需要缓存拦截器  
void openUserProfile() {
  dio.interceptors.add(CacheInterceptor());
  fetchUserData(); 
}
class EncryptInterceptor extends Interceptor {
  @override  
  void onRequest(RequestOptions options, handler) async {  
    // 统一加密所有请求体(减少重复初始化加密工具的开销)  
    if (options.data is Map) {  
      options.data = _batchEncrypt(options.data); // 批量处理数据  
    }  
    handler.next(options);  
  }  
}  
// 使用isolate或线程池并行处理多个响应解密  
onResponse: (response, handler) async {  
  final List<dynamic> dataList = response.data as List;  
  // 并行解密列表中的每条数据  
  final decryptedData = await Future.wait(  
    dataList.map((item) => compute(decrypt, item))  
  );  
  response.data = decryptedData;  
  handler.next(response);  
}  
// 对相同请求参数缓存加密结果  
final _encryptCache = HashMap<String, String>();  
onRequest: (options, handler) {  
  final key = options.uri.toString();  
  if (_encryptCache.containsKey(key)) {  
    options.data = _encryptCache[key]; // 直接使用缓存  
  } else {  
    options.data = encrypt(options.data);  
    _encryptCache[key] = options.data;  
  }  
  handler.next(options);  
}  
void onRequest(  
  RequestOptions options,  // 当前请求配置(可修改)  
  RequestInterceptorHandler handler  
)  
options.method;     // 请求方法(GET/POST等)  
options.uri;        // 请求地址  
options.headers;    // 请求头(可直接修改)  
options.queryParameters; // URL查询参数  
options.data;       // 请求体数据  
options.extra;      // 自定义扩展参数(跨拦截器传递数据)  
void onRequest(options, handler) {  
  options.headers.addAll({  
    'X-App-Version': '1.0.0',  
    'X-Device-ID': 'ABC123',  
  });  
  handler.next(options); // 传递修改后的配置  
}  
void onResponse(  
  Response response,  // 响应对象(可修改)  
  ResponseInterceptorHandler handler  
)  
response.data;      // 响应体数据(可修改为业务模型)  
response.statusCode; // HTTP状态码  
response.requestOptions; // 关联的请求配置  
void onResponse(response, handler) {  
  // 将原始JSON转换为业务模型  
  response.data = User.fromJson(response.data['user']);  
  handler.next(response);  
}  
void onError(  
  DioException err,  // 错误对象(可修改)  
  ErrorInterceptorHandler handler  
)  
err.type;          // 错误类型(如DioExceptionType.connectionTimeout)  
err.requestOptions; // 关联的请求配置  
err.response;      // 服务器返回的错误响应(若有)  
void onError(err, handler) async {  
  if (err.response.statusCode == 401) {  
    // 刷新Token后重试原请求  
    final newToken = await refreshToken();  
    err.requestOptions.headers['Authorization'] = 'Bearer $newToken';  
    final newResponse = await dio.fetch(err.requestOptions);  
    handler.resolve(newResponse); // 终止错误链,返回新响应  
  } else {  
    handler.next(err); // 继续传递错误  
  }  
}  
// 安全修改请求配置  
final newOptions = options.copyWith(  
  headers: {...options.headers, 'X-Foo': 'Bar'},  
);  
handler.next(newOptions);  
typedef Handler = Future<dynamic> Function(RequestOptions requestOptions);
dio.interceptors.add(InterceptorsWrapper(
  onRequest: (options, handler) {
    // 自定义请求拦截逻辑
    return handler.next(options);
  },
  onResponse: (response, handler) {
    // 自定义响应拦截逻辑
    return handler.next(response);
  },
  onError: (err, handler) {
    // 自定义错误拦截逻辑
    return handler.next(err);
  },
));
// 请求 -> 拦截器A的onRequest -> 拦截器B的onRequest -> 发送请求  
// 响应 -> 拦截器B的onResponse -> 拦截器A的onResponse -> 返回结果
拦截器类型职责描述
LogInterceptor仅记录请求/响应日志,不涉及数据解析或修改。
CacheInterceptor仅处理缓存逻辑(如读取缓存、更新缓存),不干预其他流程。
RetryInterceptor仅实现重试机制(如网络异常自动重试),不处理认证或加密。
AuthInterceptor仅管理认证逻辑(如Token刷新),不参与数据格式化或日志记录。
abstract class Interceptor {
  void onRequest(RequestOptions options, RequestInterceptorHandler handler);
  void onResponse(Response response, ResponseInterceptorHandler handler);
  void onError(DioException err, ErrorInterceptorHandler handler);
}
// 新增缓存拦截器(无需修改Dio源码)
dio.interceptors.add(CacheInterceptor());

// 新增性能监控拦截器
dio.interceptors.add(PerformanceInterceptor());
// 开发环境:添加日志和Mock拦截器
if (isDev) {
  dio.interceptors.add(LogInterceptor());
  dio.interceptors.add(MockInterceptor());
}

// 生产环境:移除Mock,添加加密拦截器
if (isProd) {
  dio.interceptors.removeWhere((i) => i is MockInterceptor);
  dio.interceptors.add(EncryptInterceptor());
}
设计原则实现手段业务价值
单一职责拦截器功能隔离 + 接口强制拆分代码可读性高,模块易维护、易测试。
开闭原则动态扩展机制功能扩展无需修改框架,降低升级风险。
可插拔性动态增删拦截器灵活适应多环境(开发、生产、测试)。
"岗位" 链式传递完成整个流程 Dio handler.next() handler.resolve() handler.reject() 返回结果 抛出错误 RequestOptions Response 90% 批量处理耗时操作 加密 压缩 CPU handler.next() resolve() reject() RequestOptions Response copyWith Handler handler HTTP 请求发送前 响应接收后 请求发生错误时 请求/响应 请求/响应

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多