3步打造Dio自定义拦截器:告别重复请求与冗余代码

【免费下载链接】dio A powerful HTTP client for Dart and Flutter, which supports global settings, Interceptors, FormData, aborting and canceling a request, files uploading and downloading, requests timeout, custom adapters, etc. 【免费下载链接】dio 项目地址: https://gitcode.com/gh_mirrors/di/dio

Dio是Dart和Flutter中强大的HTTP客户端,支持全局设置、拦截器、FormData、请求取消、文件上传下载等功能。拦截器作为Dio的核心特性,能够在请求/响应生命周期中处理请求配置、响应数据和错误信息,帮助开发者告别重复请求与冗余代码,提升应用性能与可维护性。

一、Dio拦截器基础:拦截器的核心价值与工作原理

Dio拦截器通过拦截请求、响应和错误三种关键节点,实现对HTTP通信的全面控制。拦截器本质上是一个实现了Interceptor抽象类的对象,包含三个核心方法:

  • 请求拦截(onRequest):在请求发送前修改配置(如添加Token、设置超时)
  • 响应拦截(onResponse):在响应返回后处理数据(如统一解析、错误转换)
  • 错误拦截(onError):在请求失败时捕获异常(如网络错误重试、登录失效处理)

Dio框架提供了两种拦截器类型:基础拦截器(Interceptor)和队列拦截器(QueuedInterceptor)。队列拦截器会将并发请求放入队列顺序执行,适合需要严格控制请求顺序的场景(如Token刷新)。

Dio拦截器工作流程示意图

二、第1步:创建基础拦截器——从理论到实践

2.1 基础拦截器实现模板

创建自定义拦截器最简单的方式是使用InterceptorsWrapper,它允许你按需实现拦截方法:

import 'package:dio/dio.dart';

class CustomInterceptor extends InterceptorsWrapper {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // 请求发送前处理
    print('请求URL: ${options.uri}');
    handler.next(options); // 必须调用next()将请求传递给下一个拦截器
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    // 响应返回后处理
    print('响应状态码: ${response.statusCode}');
    handler.next(response);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    // 错误处理
    print('请求错误: ${err.message}');
    handler.next(err);
  }
}

2.2 注册拦截器到Dio实例

创建拦截器后,通过dio.interceptors.add()方法将其添加到Dio实例:

final dio = Dio();
dio.interceptors.add(CustomInterceptor());

Dio默认包含一个ImplyContentTypeInterceptor,用于自动推断请求内容类型。如需移除默认拦截器,可调用:

dio.interceptors.removeImplyContentTypeInterceptor();

三、第2步:实现实用拦截器——解决实际开发痛点

3.1 日志拦截器:调试请求的得力助手

Dio内置的LogInterceptor可打印请求/响应详情,是开发调试的必备工具。通过配置参数可控制日志输出内容:

dio.interceptors.add(LogInterceptor(
  requestBody: true,    // 打印请求体
  responseBody: true,   // 打印响应体
  logPrint: print,      // 自定义日志输出方式(Flutter中建议使用debugPrint)
));

源码参考:dio/lib/src/interceptors/log.dart

3.2 防重复请求拦截器:优化用户体验

通过记录请求标识(如URL+参数),在请求未完成时阻止重复发送:

class AntiDuplicateInterceptor extends InterceptorsWrapper {
  final Set<String> _requestIds = {};

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    final requestId = '${options.method}-${options.uri}';
    if (_requestIds.contains(requestId)) {
      // 取消重复请求
      handler.reject(DioException(
        requestOptions: options,
        type: DioExceptionType.cancel,
        message: '重复请求已拦截',
      ));
    } else {
      _requestIds.add(requestId);
      handler.next(options);
    }
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    _removeRequestId(response.requestOptions);
    handler.next(response);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    _removeRequestId(err.requestOptions);
    handler.next(err);
  }

  void _removeRequestId(RequestOptions options) {
    final requestId = '${options.method}-${options.uri}';
    _requestIds.remove(requestId);
  }
}

四、第3步:高级拦截器技巧——队列拦截器与拦截器链

4.1 队列拦截器:处理并发请求依赖

当需要确保拦截器按顺序执行(如Token刷新后才能发送其他请求),可使用QueuedInterceptorsWrapper

class TokenRefreshInterceptor extends QueuedInterceptorsWrapper {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    if (_needRefreshToken()) {
      await _refreshToken(); // 等待Token刷新完成
    }
    options.headers['Authorization'] = 'Bearer $_token';
    handler.next(options);
  }
}

4.2 拦截器链:组合多个拦截器

Dio支持添加多个拦截器形成拦截器链,执行顺序与添加顺序一致:

dio.interceptors.addAll([
  LogInterceptor(),          // 日志拦截器(先执行)
  AntiDuplicateInterceptor(),// 防重复拦截器
  TokenRefreshInterceptor(), // Token拦截器(后执行)
]);

注意:拦截器执行顺序遵循FIFO原则,日志拦截器建议放在最后,以捕获其他拦截器的修改结果。

五、拦截器最佳实践与注意事项

  1. 单一职责原则:每个拦截器只处理一种逻辑(如日志、Token、缓存分离)
  2. 避免阻塞:耗时操作(如Token刷新)应使用异步处理
  3. 错误处理:确保每个拦截器正确调用handler.next()handler.reject()
  4. 调试技巧:使用LogInterceptor追踪拦截器执行过程
  5. 性能考量:避免在拦截器中执行复杂计算或IO操作

通过合理使用拦截器,你可以将通用HTTP逻辑(如认证、日志、缓存)与业务代码解耦,显著提升项目的可维护性。Dio的拦截器机制为开发者提供了灵活而强大的请求处理能力,是构建健壮网络层的关键工具。

【免费下载链接】dio A powerful HTTP client for Dart and Flutter, which supports global settings, Interceptors, FormData, aborting and canceling a request, files uploading and downloading, requests timeout, custom adapters, etc. 【免费下载链接】dio 项目地址: https://gitcode.com/gh_mirrors/di/dio

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐