【Flutter 必备插件】HTTP 封装 dio

什么是 dio

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

实战:HTTP 网络请求封装

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());
    }
  }
}

使用示例

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. 证书验证问题
// 忽略证书验证
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. 请求取消后的内存泄露
// 在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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YueYa-Tech

你的鼓励是我坚持的源泉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值