【Flutter 必备插件】HTTP 封装 dio

什么是 dio

dio 是一个强大的 HTTP 网络请求库,支持全局配置、Restful API、FormData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时、自定义适配器、转换器等。

实战:HTTP 网络请求封装

dart 复制代码
dart
 体验AI代码助手
 代码解读
复制代码
class HttpUtil {

  late Dio _dio;
  // 单例模式
  static final HttpUtil _instance = HttpUtil._internal();

  factory HttpUtil() => _instance;

  HttpUtil._internal() {

    _dio = Dio(
        BaseOptions(
            baseUrl: AppConst.baseUrl,
            headers: {
              'platformId': AppConst.platformId,
              'tenant-id': 1,
            }
        )
    );

    _dio.interceptors.add(LogInterceptor(responseBody: true));

    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (RequestOptions options, RequestInterceptorHandler handler) async {

        if (options.headers['Authorization'] == null && UserStorage.getAccessToken() != null) {
          options.headers['Authorization'] = 'Bearer ${UserStorage.getAccessToken()}';
        }

        return handler.next(options);
      },
      onResponse: (Response<dynamic> response, ResponseInterceptorHandler handler) async {

        if (response.data['code'] == 0 || response.data['code'] == "00000") {

        } else if (response.data['code'] == 401) {
            if (UserStorage.getRefreshToke() != null && !response.requestOptions.path.contains('/auth/refresh')) {

              ApiResponse<Token> newToken = await _refreshToken(UserStorage.getRefreshToke()!);
              UserStorage.setToken(newToken.data!);

              response.requestOptions.headers['Authorization'] = 'Bearer ${newToken.data?.accessToken}';

              _dio.options.headers['Authorization'] = 'Bearer ${newToken.data?.accessToken}';

              final reResponse = await _dio.fetch(response.requestOptions);
              return handler.resolve(reResponse);
            } else {

              _dio.options.headers['Authorization'] = null;

              UserStorage.clearAll();
            }
        } else {
          // todo toast 展示
        }

        return handler.next(response);
      },
      onError: (DioException error, ErrorInterceptorHandler handler) async {

        return handler.next(error);
      },
    ));
  }

  Future<T> get<T> ( String path, { Map<String, dynamic>? params, Options? options, CancelToken? cancelToken} ) async {
    try {
      final response = await _dio.get(
        path,
        queryParameters: params,
        options: options,
        cancelToken: cancelToken,
      );
      return response.data;
    } catch (e) {
      throw ApiException(e.toString());
    }
  }

  Future<T> post <T> ( String path, { dynamic data, Map<String, dynamic>? params, Options? options, CancelToken? cancelToken,}) async {
    try {
      final response = await _dio.post(
        path, data:
        data,
        queryParameters: params,
        options: options,
        cancelToken: cancelToken,
      );
      return response.data;
    } catch (e) {
      throw ApiException(e.toString());
    }
  }
}

使用示例

javascript 复制代码
javascript
 体验AI代码助手
 代码解读
复制代码
static Future<ApiResponse<Token>> _refreshToken(String refreshToken) async {
    final response = await HttpUtil().post('/system/auth/refresh-token',
        params: { 'refreshToken': refreshToken} );
    return ApiResponse<Token>.fromJson(response, (json) => Token.fromJson(json));

性能优化建议

  1. 合理使用拦截器

    • 避免在拦截器中进行耗时操作
    • 使用异步操作时注意处理异常
  2. 请求优化

    • 合理设置超时时间
    • 使用cancelToken取消不必要的请求
    • 避免频繁的重复请求
  3. 缓存策略

    • 针对不常变化的数据实现缓存
    • 设置合理的缓存过期时间
    • 考虑使用本地存储持久化缓存
  4. 错误处理

    • 实现统一的错误处理机制
    • 合理使用重试机制
    • 提供友好的错误提示

FAQ【干货】

  1. 证书验证问题
ini 复制代码
ini
 体验AI代码助手
 代码解读
复制代码
// 忽略证书验证
dio.options.validateStatus = (status) {
  return status! < 500;
};

// 或者自定义证书验证
(dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate = 
  (HttpClient client) {
    client.badCertificateCallback =
        (X509Certificate cert, String host, int port) => true;
    return client;
  };
  1. 请求取消后的内存泄露
scss 复制代码
scss
 体验AI代码助手
 代码解读
复制代码
// 在dispose时取消所有请求
final _cancelTokens = <CancelToken>[];

void addCancelToken(CancelToken token) {
  _cancelTokens.add(token);
}

@override
void dispose() {
  for (final token in _cancelTokens) {
    token.cancel();
  }
  _cancelTokens.clear();
  super.dispose();
}
相关推荐
恋猫de小郭1 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
明君879976 小时前
Flutter 如何给图片添加多行文字水印
前端·flutter
四眼肥鱼13 小时前
flutter 利用flutter_libserialport 实现SQ800 串口通信
前端·flutter
火柴就是我1 天前
让我们实现一个更好看的内部阴影按钮
android·flutter
王晓枫1 天前
flutter接入三方库运行报错:Error running pod install
前端·flutter
shankss2 天前
Flutter 下拉刷新库 pull_to_refresh_plus 设计与实现分析
flutter
忆江南2 天前
iOS 深度解析
flutter·ios
明君879972 天前
Flutter 实现 AI 聊天页面 —— 记一次 Markdown 数学公式显示的踩坑之旅
前端·flutter
恋猫de小郭2 天前
移动端开发稳了?AI 目前还无法取代客户端开发,小红书的论文告诉你数据
前端·flutter·ai编程
MakeZero2 天前
Flutter那些事-交互式组件
flutter