【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));

性能优化建议

合理使用拦截器

避免在拦截器中进行耗时操作

使用异步操作时注意处理异常

请求优化

合理设置超时时间

使用cancelToken取消不必要的请求

避免频繁的重复请求

缓存策略

针对不常变化的数据实现缓存

设置合理的缓存过期时间

考虑使用本地存储持久化缓存

错误处理

实现统一的错误处理机制

合理使用重试机制

提供友好的错误提示

FAQ【干货】

证书验证问题

// 忽略证书验证

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;

  };

请求取消后的内存泄露

// 在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();

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容