【Flutter 必备插件】HTTP 封装 dio

什么是 dio

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

实战:HTTP 网络请求封装

dart 复制代码
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 复制代码
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 复制代码
// 忽略证书验证
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 复制代码
// 在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();
}
相关推荐
种时光的人8 小时前
无状态HTTP的“记忆”方案:Spring Boot中Cookie&Session全栈实战
服务器·spring boot·后端·http
FFFfengZiz.9 小时前
HTTP相关
网络·网络协议·http
清静诗意12 小时前
FRP v0.65.0 内网穿透专业指南(SSH + HTTP/HTTPS 一体化配置)
http·https·ssh·frp
艾菜籽12 小时前
网络原理-HTTP补充2
网络·网络协议·http
fxshy12 小时前
解决 Web 应用加载地图资源时的 HTTP 与 HTTPS 混合内容问题
前端·网络协议·http
周某人姓周12 小时前
安全初级(二)HTTP
网络协议·安全·http
李贺梖梖13 小时前
Tomcat&Http协议
java·http·tomcat
Bryce李小白1 天前
Flutter 自定义 View 权威指引
flutter
恋猫de小郭1 天前
Fluttercon EU 2025 :Let‘s go far with Flutter
android·开发语言·flutter·ios·golang
两个西柚呀1 天前
nodejs中http模块搭建web服务器
服务器·前端·http