flutter 整合dio

发布时间:2022-01-30 16:00:27

这个标题在搜索下有很多文章,但还是决定记录下来。也可能是flutter版本升级太快了 导致即使按网上的流程整合还是有很多问题,主要是很多没有写明依赖的包以及版本

1.引用依赖

dio: ^4.0.4
cookie_jar: 3.0.1
dio_cookie_manager: ^2.0.0
shared_preferences: ^2.0.12

2.引入相关的包

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart'; //kDebugMode 使用
import 'package:shared_preferences/shared_preferences.dart';

3.整合的代码

// 封装 dio 请求类
class HttpHelper {
  // dio 的 options 配置
  static final BaseOptions _options = BaseOptions(
    baseUrl: "", // 请求的baseUrl
    connectTimeout: 10000, // 连接超时时间
    receiveTimeout: 15000, // 响应超时时间
    contentType: 'application/x-www-form-urlencoded;charset=utf-8',
  );

  // get 请求
  static get(url, {pathParams, params, needCode = false, cancelToken}) async {
    return await request(
        url, pathParams, params, 'GET', null, needCode, cancelToken);
  }

  // post 请求
  static post(url, {pathParams, params, needCode = false, cancelToken}) async {
    return await request(
        url, pathParams, params, 'POST', null, needCode, cancelToken);
  }

  
  static request(urlName, pathParams, params, method, header, needCode,
      cancelToken) async {
    // 处理URL ,通过 urlName 在 urlPath 中匹配相应的 url 路径地址
    String url = urlName;

    // get请求处理
    if (pathParams != null) {
      // 处理  https://test_api.com/user/:id/:name => https://test_api.com/user/123/zhangsan  请求连接
      pathParams.forEach((key, value) {
        if (url.contains(key)) {
          url = url.replaceAll(":$key", value.toString());
        }
      });
    } else if (pathParams == null && method == 'GET') {
      // 处理 https://test_api.com/user?id=123&name=zhangsan 请求连接
      url += '?';
      params.forEach((key, value) {
        url += '$key=$value&';
      });
    }
    // 读取本地缓存中的数据
    dynamic sp = await SharedPreferences.getInstance();
    Map headers = {};
    // 存储 请求头 参数
    if (header != null) {
      headers.addAll(header);
    }
    //  授权信息 Authorization / token
    if (sp.get('token') == null && sp.get('Authorization') == null) {
      // 处理授权信息不存在的逻辑,即 重新登录 或者 获取授权信息
    } else {
      // 获取授权信息( token、Authorization 一般出现一个或者两都存在)
      if (sp.get('token') != null) {
        headers['token'] = sp.get('token');
      }
      if (sp.get('Authorization') != null) {
        headers['Authorization'] = sp.get('Authorization');
      }
    }

    // 设置请求头
    _options.headers = Map<String, dynamic>.from(headers);

    // 初始化 Dio
    Dio _dio = Dio(_options);

    // 请求拦击
    _dio.interceptors.add(InterceptorsWrapper(onRequest: (request, handler) {
      return handler.next(request);
    }, onError: (e, handler) async {
      if (e.response?.statusCode == 401) {}
    }));

    late Response response; //late关键字使用 must be assigned before it can be used
    // dio 请求处理
    try {
      response = await _dio.request(url,
          data: params,
          options: Options(method: method),
          cancelToken: cancelToken);
    } on DioError catch (e) {
      // 请求错误处理  ,错误码 e.response.statusCode

      handleHttpError((e.response?.statusCode)!);
      if (CancelToken.isCancel(e)) {
        if (kDebugMode) {
          print('请求取消! ' + e.message);
        }
      } else {
        // 请求发生错误处理
        if (e.type == DioErrorType.connectTimeout) {
          if (kDebugMode) {
            print('连接超时');
          }
        }
      }
    }

    // 对相应code的处理
    if (response == null) {
      if (kDebugMode) {
        print('响应错误');
      }
    } else if (needCode) {
      // 需要返回code
      return response.data;
    } else if (!needCode) {
      // 不需要返回 code ,统一处理不同 code 的情况
      if (response.data != '' && response.data != null) {
        // 可对其他不同值的 code 做额外处理
        return response.data['data'];
      } else {
        if (kDebugMode) {
          print('其他数据类型处理');
        }
        return response;
      }
    }
  }

  /*
        * @description: 处理Http错误码
        * @param {type} 错误码
        * @return {type}
        */
  static handleHttpError(int errorCode) {
    if (kDebugMode) {
      print('http错误码: $errorCode');
    }
  }
}

代码中的response变量如果不加上late 会出现以下错误代码

must be assigned before it can be used

Card image cap
APP STORE
Card image cap
应用宝
Card image cap
小米
Card image cap
华为