Flutter网络通信-封装Dio

前言

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

Dio的pub地址为:dio | Dart package

封装要求

  • 能够使用get、post、put、patch、delete、postForm、postStream请求
  • 能够使用token
  • 能够取消请求
  • 不论网络通信是否成功,返回的格式保持一致

封装步骤

1.添加依赖

复制代码
dart pub add dio

2.创建一个名称为HttpUtil的工厂函数

复制代码
class HttpUtil {
  static final HttpUtil _instance = HttpUtil.internal();
  factory HttpUtil() => _instance;
}

在HttpUtil.internal中初始化Dio

  • baseUrl是请求基地址,根据自己的需求转换

  • InterceptorsWrapper中添加了拦截器

  • 不论请求成功与否,返回的data都是DioResponse类型,我们根据DioResponse对数据进行解析

    HttpUtil.internal() {
    // BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数
    BaseOptions options = BaseOptions(
    //请求基地址
    baseUrl: SERVER_API_URL,

    复制代码
      // baseUrl: storage.read(key: STORAGE_KEY_APIURL) ?? SERVICE_API_BASEURL,
      //连接服务器超时时间
      connectTimeout: const Duration(seconds: 20),
      // 响应流上前后两次接受到数据的间隔
      receiveTimeout: const Duration(seconds: 20),
      // Http请求头.
      headers: {},
    
      /// 请求的Content-Type,默认值是"application/json; charset=utf-8".
      /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
      /// 可以设置此选项为 `Headers.formUrlEncodedContentType`,  这样[Dio]
      /// 就会自动编码请求体.
      contentType: 'application/json; charset=utf-8',
    
      /// [responseType] 表示期望以那种格式(方式)接受响应数据。
      /// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.
      ///
      /// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。
      /// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.
      ///
      /// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.
      responseType: ResponseType.json,
    );
    dio = Dio(options);
    // CookieJar   Dart 中用于 http 请求的 cookie 管理器,您可以通过它轻松处理复杂的 cookie 策略并持久化 cookie。
    // CookieJar cookieJar = CookieJar();
    // dio.interceptors.add(CookieManager(cookieJar));
    
    // 添加拦截器
    dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
          /// 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。
          ///这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.
    
          /// 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。
          /// 这样请求将被中止并触发异常,上层catchError会被调用。
          ///
          return handler.next(options);
        },
        onResponse: (response, handler) {
          // 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。
          //这样请求将被中止并触发异常,上层catchError会被调用。
          // 请求成功是对数据做基本处理
    
          if (response.statusCode == 200) {
            response.data =
                DioResponse(code: 200, message: "请求成功啦", data: response.data);
          } else {
            response.data = DioResponse(
                code: response.statusCode,
                message: "请求失败啦",
                data: response.data);
          }
          return handler.next(response);
        },
        onError: (e, handler) {
          //停止加载
          // Loading.dismiss();
          print("-=-=-=-onError$e,-----$handler");
    
          EasyLoading.instance.userInteractions = true;
          EasyLoading.dismiss();
          DioResponse? eInfo;
          if ("$e".contains("The request connection took longer")) {
            eInfo = DioResponse(code: -1, message: "连接超时", data: "");
          } else {
            eInfo = createErrorEntity(e);
          }
          onError(eInfo);
          Response response = Response(data: eInfo, requestOptions: RequestOptions());
          return handler.resolve(response); //continue
    
          // 如果你想完成请求并返回一些自定义数据,可以resolve 一个`Response`,如`handler.resolve(response)`。
          // 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.
        },
      ),
    );

    }

3.定义DioResponse

  • code是请求返回的状态码

  • data是后端返回的数据

    class DioResponse {
    /// 消息(例如成功消息文字/错误消息文字)
    final String message;

    复制代码
    /// 自定义code(可根据内部定义方式)
    final int? code;
    
    /// 接口返回的数据
    final T data;
    
    /// 需要添加更多
    /// .........
    
    DioResponse({
      required this.message,
      required this.data,
      required this.code,
    });
    factory DioResponse.fromJson(Map<String, dynamic> json) => DioResponse(
          code: json["code"],
          message: json["message"],
          data: json["data"],
        );
    Map<String, dynamic> toJson() => {
          "message": message,
          "data": data,
          "code": code,
        };

    }

4.对错误请求进行DioResponse处理

复制代码
//错误信息
  DioResponse createErrorEntity(DioError error) {
    // print('error.type${error.type}');
    var data = error.response?.data;
    print(
        "进入了错误信息:error.type:${error.type},错误的码:¥「${error.response!.statusCode},,data:¥${data}");
    switch (error.type) {
      case DioErrorType.cancel:
        return DioResponse(code: -1, message: "请求取消", data: data);
      case DioErrorType.connectionTimeout:
        return DioResponse(code: -1, message: "连接超时", data: data);
      case DioErrorType.sendTimeout:
        return DioResponse(code: -1, message: "请求超时", data: data);
      case DioErrorType.receiveTimeout:
        return DioResponse(code: -1, message: "响应超时", data: data);
      case DioErrorType.badResponse:
        try {
          print("data:$data");
          int errCode =
              error.response != null ? error.response!.statusCode! : -1;
 
          return DioResponse(
              code: errCode, message: data["message"], data: data);
        } catch (e) {
          return DioResponse(code: -1, message: "badResponse抛出了异常", data: e);
        }
 
      case DioErrorType.unknown:
        {
          try {
            int errCode =
                error.response != null ? error.response!.statusCode! : -1;
 
            switch (errCode) {
              case 400:
                return DioResponse(
                    code: errCode, message: "请求语法错误", data: data);
              case 401:
                return DioResponse(code: errCode, message: "没有权限", data: data);
              case 403:
                return DioResponse(
                    code: errCode, message: "服务器拒绝执行", data: data);
              case 404:
                return DioResponse(
                    code: errCode, message: "无法连接服务器", data: data);
              case 405:
                return DioResponse(
                    code: errCode, message: "请求方法被禁止", data: data);
              case 500:
                return DioResponse(
                    code: errCode, message: "服务器内部错误", data: data);
              case 502:
                return DioResponse(code: errCode, message: "无效的请求", data: data);
              case 503:
                return DioResponse(code: errCode, message: "服务器挂了", data: data);
              case 505:
                return DioResponse(
                    code: errCode, message: "不支持HTTP协议请求", data: data);
              default:
                return DioResponse(
                    code: errCode,
                    message: error.response != null
                        ? error.response!.statusMessage!
                        : "其他状态字异常",
                    data: data);
            }
          } on Exception catch (_) {
            return DioResponse(code: -1, message: "unknown抛出了异常", data: data);
          }
        }
      default:
        {
          return DioResponse(
              code: -1, message: error.message.toString(), data: data);
        }
    }
  }

5.对错误信息进行统一的处理

复制代码
//error进行统一处理
 onError(DioResponse eInfo) {
   debugPrint('错误----代码:${eInfo.code.toString()}, 错误内容:${eInfo.message}');
   String errText = '';
   switch (eInfo.code) {
     case 401: //401提示什么错误或者做些什么操作,比如token过期退出登录
 
       switch (eInfo.message) {
         case "Token has expired":
         case "Authentication failed":
           errText = "账号登录已过期,请重新登陆".tr;
           EasyLoading.showError(errText);
           Get.offNamed(AppRoutes.SIGN_IN);
           break;
         case "Invalid username or password":
           EasyLoading.showError("账号或密码不正确".tr);
           break;
         case "User account is not active":
         case "User account is locked due to security policy":
           break;
       }
 
       break;
     case 501:
       switch (eInfo.message) {
         case "The user does not exist, please register!":
           errText = "该账号不存在".tr;
           EasyLoading.showError(errText);
           break;
         case "User already exists!":
           errText = "用户已存在".tr;
           EasyLoading.showError(errText);
           break;
       }
 
       break;
     case 509:
       print("+++++++++++++++++++");
       errText = "验证码有误,请重新获取".tr;
       EasyLoading.showError(errText);
       break;
 
     case 511:
       errText = "验证码以过期,请重新输入".tr;
       EasyLoading.showError(errText);
       break;
     case 403:
       errText = "该账号没有权限登录,请联系管理员".tr;
       EasyLoading.showError(errText);
       break;
     case -1:
       EasyLoading.showError(eInfo.message);
       break;
 
     default:
       //用弹窗提示错误
       errText = "未知错误".tr;
       EasyLoading.showError(errText);
   }
 }

6.配置请求类型和取消请求功能

复制代码
//error进行统一处理
  onError(DioResponse eInfo) {
    debugPrint('错误----代码:${eInfo.code.toString()}, 错误内容:${eInfo.message}');
    String errText = '';
    switch (eInfo.code) {
      case 401: //401提示什么错误或者做些什么操作,比如token过期退出登录
 
        switch (eInfo.message) {
          case "Token has expired":
          case "Authentication failed":
            errText = "账号登录已过期,请重新登陆".tr;
            EasyLoading.showError(errText);
            Get.offNamed(AppRoutes.SIGN_IN);
            break;
          case "Invalid username or password":
            EasyLoading.showError("账号或密码不正确".tr);
            break;
          case "User account is not active":
          case "User account is locked due to security policy":
            break;
        }
 
        break;
      case 501:
        switch (eInfo.message) {
          case "The user does not exist, please register!":
            errText = "该账号不存在".tr;
            EasyLoading.showError(errText);
            break;
          case "User already exists!":
            errText = "用户已存在".tr;
            EasyLoading.showError(errText);
            break;
        }
 
        break;
      case 509:
        print("+++++++++++++++++++");
        errText = "验证码有误,请重新获取".tr;
        EasyLoading.showError(errText);
        break;
 
      case 511:
        errText = "验证码以过期,请重新输入".tr;
        EasyLoading.showError(errText);
        break;
      case 403:
        errText = "该账号没有权限登录,请联系管理员".tr;
        EasyLoading.showError(errText);
        break;
      case -1:
        EasyLoading.showError(eInfo.message);
        break;
 
      default:
        //用弹窗提示错误
        errText = "未知错误".tr;
        EasyLoading.showError(errText);
    }
  }
 
//错误信息
  DioResponse createErrorEntity(DioError error) {
    // print('error.type${error.type}');
    var data = error.response?.data;
    print(
        "进入了错误信息:error.type:${error.type},错误的码:¥「${error.response!.statusCode},,data:¥${data}");
    switch (error.type) {
      case DioErrorType.cancel:
        return DioResponse(code: -1, message: "请求取消", data: data);
      case DioErrorType.connectionTimeout:
        return DioResponse(code: -1, message: "连接超时", data: data);
      case DioErrorType.sendTimeout:
        return DioResponse(code: -1, message: "请求超时", data: data);
      case DioErrorType.receiveTimeout:
        return DioResponse(code: -1, message: "响应超时", data: data);
      case DioErrorType.badResponse:
        try {
          print("data:$data");
          int errCode =
              error.response != null ? error.response!.statusCode! : -1;
 
          return DioResponse(
              code: errCode, message: data["message"], data: data);
        } catch (e) {
          return DioResponse(code: -1, message: "badResponse抛出了异常", data: e);
        }
 
      case DioErrorType.unknown:
        {
          try {
            int errCode =
                error.response != null ? error.response!.statusCode! : -1;
 
            switch (errCode) {
              case 400:
                return DioResponse(
                    code: errCode, message: "请求语法错误", data: data);
              case 401:
                return DioResponse(code: errCode, message: "没有权限", data: data);
              case 403:
                return DioResponse(
                    code: errCode, message: "服务器拒绝执行", data: data);
              case 404:
                return DioResponse(
                    code: errCode, message: "无法连接服务器", data: data);
              case 405:
                return DioResponse(
                    code: errCode, message: "请求方法被禁止", data: data);
              case 500:
                return DioResponse(
                    code: errCode, message: "服务器内部错误", data: data);
              case 502:
                return DioResponse(code: errCode, message: "无效的请求", data: data);
              case 503:
                return DioResponse(code: errCode, message: "服务器挂了", data: data);
              case 505:
                return DioResponse(
                    code: errCode, message: "不支持HTTP协议请求", data: data);
              default:
                return DioResponse(
                    code: errCode,
                    message: error.response != null
                        ? error.response!.statusMessage!
                        : "其他状态字异常",
                    data: data);
            }
          } on Exception catch (_) {
            return DioResponse(code: -1, message: "unknown抛出了异常", data: data);
          }
        }
      default:
        {
          return DioResponse(
              code: -1, message: error.message.toString(), data: data);
        }
    }
  }
 
  /// 取消请求
  /// 同一个cancel token 可以用于多个请求,当一个cancel token取消时,所有使用该cancel token的请求都会被取消。
  /// 所以参数可选
  void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }
 
  /// 读取本地配置
  Map<String, dynamic>? getAuthorizationHeader() {
    var headers = <String, dynamic>{};
    var token = StorageUtil().read("token");
    print("token");
    if (token != null) {
      headers['X-Authorization'] = 'Bearer $token';
    }
    return headers;
  }
 
  /// restful get 操作
  /// refresh 是否下拉刷新 默认 false
  /// noCache 是否不缓存 默认 true
  /// list 是否列表 默认 false
  /// cacheKey 缓存key
  /// cacheDisk 是否磁盘缓存
  Future get(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    bool refresh = false,
    bool noCache = !CACHE_ENABLE,
    bool list = false,
    String cacheKey = '',
    bool cacheDisk = false,
    CancelToken? canceltoken,
    Map<String, dynamic>? data,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
 
    try {
      print("入参:$path--$data");
      var response = await dio.get(
        path,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: canceltoken ?? cancelToken,
        data: data,
      );
      print("+++++++++++++++:$response");
      return response.data;
    } catch (e) {
      print("出现了错误$e");
    }
  }
 
  /// restful post 操作
  Future post(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? canceltoken,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
 
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    try {
      var response = await dio.post(
        path,
        data: data,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: canceltoken ?? cancelToken,
      );
      return response.data;
    } catch (e) {
      print("出现了错误:$e");
      return e;
    }
  }
 
  /// restful put 操作
  Future put(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.put(
      path,
      data: data,
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful patch 操作
  Future patch(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.patch(
      path,
      data: data,
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful delete 操作
  Future delete(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.delete(
      path,
      data: data,
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful post form 表单提交操作
  Future postForm(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.post(
      path,
      data: FormData.fromMap(data),
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful post Stream 流数据
  Future postStream(
    String path, {
    dynamic data,
    int dataLength = 0,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    requestOptions.headers!.addAll({
      Headers.contentLengthHeader: dataLength.toString(),
    });
    var response = await dio.post(
      path,
      data: Stream.fromIterable(data.map((e) => [e])),
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
}

7.全部代码

复制代码
import 'dart:math';
 
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart' as tr;
import 'package:get/get_core/src/get_main.dart';
import 'package:my_app/common/routes/routes.dart';
import 'package:my_app/common/utils/utils.dart';
import 'package:my_app/common/value/serve.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
// import 'package:get/get.dart';
// import 'package:dio/src/form_data.dart';
import './../value/cache.dart';
 
class HttpUtil {
  static final HttpUtil _instance = HttpUtil.internal();
  factory HttpUtil() => _instance;
 
  late Dio dio;
  //可以通过 CancelToken 来取消发起的请求
  CancelToken cancelToken = CancelToken();
 
  HttpUtil.internal() {
    // BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数
    BaseOptions options = BaseOptions(
      //请求基地址
      baseUrl: SERVER_API_URL,
 
      // baseUrl: storage.read(key: STORAGE_KEY_APIURL) ?? SERVICE_API_BASEURL,
      //连接服务器超时时间
      connectTimeout: const Duration(seconds: 20),
      // 响应流上前后两次接受到数据的间隔
      receiveTimeout: const Duration(seconds: 20),
      // Http请求头.
      headers: {},
 
      /// 请求的Content-Type,默认值是"application/json; charset=utf-8".
      /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
      /// 可以设置此选项为 `Headers.formUrlEncodedContentType`,  这样[Dio]
      /// 就会自动编码请求体.
      contentType: 'application/json; charset=utf-8',
 
      /// [responseType] 表示期望以那种格式(方式)接受响应数据。
      /// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.
      ///
      /// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。
      /// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.
      ///
      /// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.
      responseType: ResponseType.json,
    );
    dio = Dio(options);
    // CookieJar   Dart 中用于 http 请求的 cookie 管理器,您可以通过它轻松处理复杂的 cookie 策略并持久化 cookie。
    // CookieJar cookieJar = CookieJar();
    // dio.interceptors.add(CookieManager(cookieJar));
 
    // 添加拦截器
    dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
          /// 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。
          ///这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.
 
          /// 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。
          /// 这样请求将被中止并触发异常,上层catchError会被调用。
          ///
          return handler.next(options);
        },
        onResponse: (response, handler) {
          // 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。
          //这样请求将被中止并触发异常,上层catchError会被调用。
          // 请求成功是对数据做基本处理
 
          if (response.statusCode == 200) {
            response.data =
                DioResponse(code: 200, message: "请求成功啦", data: response.data);
          } else {
            response.data = DioResponse(
                code: response.statusCode,
                message: "请求失败啦",
                data: response.data);
          }
          // 对某些单独的url返回数据做特殊处理
          // if (response.requestOptions.baseUrl.contains("???????")) {
          //   //....
          // }
 
          return handler.next(response);
        },
        onError: (e, handler) {
          //停止加载
          // Loading.dismiss();
          print("-=-=-=-onError$e,-----$handler");
 
          EasyLoading.instance.userInteractions = true;
          EasyLoading.dismiss();
          DioResponse? eInfo;
          if ("$e".contains("The request connection took longer")) {
            eInfo = DioResponse(code: -1, message: "连接超时", data: "");
          } else {
            eInfo = createErrorEntity(e);
          }
 
          // print("111111111:$eInfo");
 
          onError(eInfo);
 
          Response response =
              Response(data: eInfo, requestOptions: RequestOptions());
 
          // e.data =eInfo;
 
          return handler.resolve(response); //continue
 
          // 如果你想完成请求并返回一些自定义数据,可以resolve 一个`Response`,如`handler.resolve(response)`。
          // 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.
        },
      ),
    );
  }
 
  //error进行统一处理
  onError(DioResponse eInfo) {
    debugPrint('错误----代码:${eInfo.code.toString()}, 错误内容:${eInfo.message}');
    String errText = '';
    switch (eInfo.code) {
      case 401: //401提示什么错误或者做些什么操作,比如token过期退出登录
 
        switch (eInfo.message) {
          case "Token has expired":
          case "Authentication failed":
            errText = "账号登录已过期,请重新登陆".tr;
            EasyLoading.showError(errText);
            Get.offNamed(AppRoutes.SIGN_IN);
            break;
          case "Invalid username or password":
            EasyLoading.showError("账号或密码不正确".tr);
            break;
          case "User account is not active":
          case "User account is locked due to security policy":
            break;
        }
 
        break;
      case 501:
        switch (eInfo.message) {
          case "The user does not exist, please register!":
            errText = "该账号不存在".tr;
            EasyLoading.showError(errText);
            break;
          case "User already exists!":
            errText = "用户已存在".tr;
            EasyLoading.showError(errText);
            break;
        }
 
        break;
      case 509:
        print("+++++++++++++++++++");
        errText = "验证码有误,请重新获取".tr;
        EasyLoading.showError(errText);
        break;
 
      case 511:
        errText = "验证码以过期,请重新输入".tr;
        EasyLoading.showError(errText);
        break;
      case 403:
        errText = "该账号没有权限登录,请联系管理员".tr;
        EasyLoading.showError(errText);
        break;
      case -1:
        EasyLoading.showError(eInfo.message);
        break;
 
      default:
        //用弹窗提示错误
        errText = "未知错误".tr;
        EasyLoading.showError(errText);
    }
  }
 
//错误信息
  DioResponse createErrorEntity(DioError error) {
    // print('error.type${error.type}');
    var data = error.response?.data;
    print(
        "进入了错误信息:error.type:${error.type},错误的码:¥「${error.response!.statusCode},,data:¥${data}");
    switch (error.type) {
      case DioErrorType.cancel:
        return DioResponse(code: -1, message: "请求取消", data: data);
      case DioErrorType.connectionTimeout:
        return DioResponse(code: -1, message: "连接超时", data: data);
      case DioErrorType.sendTimeout:
        return DioResponse(code: -1, message: "请求超时", data: data);
      case DioErrorType.receiveTimeout:
        return DioResponse(code: -1, message: "响应超时", data: data);
      case DioErrorType.badResponse:
        try {
          print("data:$data");
          int errCode =
              error.response != null ? error.response!.statusCode! : -1;
 
          return DioResponse(
              code: errCode, message: data["message"], data: data);
        } catch (e) {
          return DioResponse(code: -1, message: "badResponse抛出了异常", data: e);
        }
 
      case DioErrorType.unknown:
        {
          try {
            int errCode =
                error.response != null ? error.response!.statusCode! : -1;
 
            switch (errCode) {
              case 400:
                return DioResponse(
                    code: errCode, message: "请求语法错误", data: data);
              case 401:
                return DioResponse(code: errCode, message: "没有权限", data: data);
              case 403:
                return DioResponse(
                    code: errCode, message: "服务器拒绝执行", data: data);
              case 404:
                return DioResponse(
                    code: errCode, message: "无法连接服务器", data: data);
              case 405:
                return DioResponse(
                    code: errCode, message: "请求方法被禁止", data: data);
              case 500:
                return DioResponse(
                    code: errCode, message: "服务器内部错误", data: data);
              case 502:
                return DioResponse(code: errCode, message: "无效的请求", data: data);
              case 503:
                return DioResponse(code: errCode, message: "服务器挂了", data: data);
              case 505:
                return DioResponse(
                    code: errCode, message: "不支持HTTP协议请求", data: data);
              default:
                return DioResponse(
                    code: errCode,
                    message: error.response != null
                        ? error.response!.statusMessage!
                        : "其他状态字异常",
                    data: data);
            }
          } on Exception catch (_) {
            return DioResponse(code: -1, message: "unknown抛出了异常", data: data);
          }
        }
      default:
        {
          return DioResponse(
              code: -1, message: error.message.toString(), data: data);
        }
    }
  }
 
  /// 取消请求
  /// 同一个cancel token 可以用于多个请求,当一个cancel token取消时,所有使用该cancel token的请求都会被取消。
  /// 所以参数可选
  void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }
 
  /// 读取本地配置
  Map<String, dynamic>? getAuthorizationHeader() {
    var headers = <String, dynamic>{};
    var token = StorageUtil().read("token");
    print("token");
    if (token != null) {
      headers['X-Authorization'] = 'Bearer $token';
    }
    return headers;
  }
 
  /// restful get 操作
  /// refresh 是否下拉刷新 默认 false
  /// noCache 是否不缓存 默认 true
  /// list 是否列表 默认 false
  /// cacheKey 缓存key
  /// cacheDisk 是否磁盘缓存
  Future get(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    bool refresh = false,
    bool noCache = !CACHE_ENABLE,
    bool list = false,
    String cacheKey = '',
    bool cacheDisk = false,
    CancelToken? canceltoken,
    Map<String, dynamic>? data,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
 
    try {
      print("入参:$path--$data");
      var response = await dio.get(
        path,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: canceltoken ?? cancelToken,
        data: data,
      );
      print("+++++++++++++++:$response");
      return response.data;
    } catch (e) {
      print("出现了错误$e");
    }
  }
 
  /// restful post 操作
  Future post(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? canceltoken,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
 
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    try {
      var response = await dio.post(
        path,
        data: data,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: canceltoken ?? cancelToken,
      );
      return response.data;
    } catch (e) {
      print("出现了错误:$e");
      return e;
    }
  }
 
  /// restful put 操作
  Future put(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.put(
      path,
      data: data,
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful patch 操作
  Future patch(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.patch(
      path,
      data: data,
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful delete 操作
  Future delete(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.delete(
      path,
      data: data,
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful post form 表单提交操作
  Future postForm(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    var response = await dio.post(
      path,
      data: FormData.fromMap(data),
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
 
  /// restful post Stream 流数据
  Future postStream(
    String path, {
    dynamic data,
    int dataLength = 0,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    Options requestOptions = options ?? Options();
    requestOptions.headers = requestOptions.headers ?? {};
    Map<String, dynamic>? authorization = getAuthorizationHeader();
    if (authorization != null) {
      requestOptions.headers!.addAll(authorization);
    }
    requestOptions.headers!.addAll({
      Headers.contentLengthHeader: dataLength.toString(),
    });
    var response = await dio.post(
      path,
      data: Stream.fromIterable(data.map((e) => [e])),
      queryParameters: queryParameters,
      options: requestOptions,
      cancelToken: cancelToken,
    );
    return response.data;
  }
}
 
class DioResponse<T> {
  /// 消息(例如成功消息文字/错误消息文字)
  final String message;
 
  /// 自定义code(可根据内部定义方式)
  final int? code;
 
  /// 接口返回的数据
  final T data;
 
  /// 需要添加更多
  /// .........
 
  DioResponse({
    required this.message,
    required this.data,
    required this.code,
  });
  factory DioResponse.fromJson(Map<String, dynamic> json) => DioResponse(
        code: json["code"],
        message: json["message"],
        data: json["data"],
      );
  Map<String, dynamic> toJson() => {
        "message": message,
        "data": data,
        "code": code,
      };
}
相关推荐
梦想的颜色6 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
yuanlaile1 天前
2026年全新Flutter 跨平台开发全栈学习资料整理
flutter·getx·鸿蒙 next·flutter开发鸿蒙·flutter入门实战·flutter全栈
恋猫de小郭1 天前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白2 天前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫2 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘2 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185822 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙
恋猫de小郭2 天前
Flutter + EmbeddingGemma 2,谷歌发布完全端侧的 AI Edge Foresight
android·前端·flutter
君赏3 天前
基于 FlutterPatch 快速接入 Flutter 热更新
flutter
律宏阔3 天前
Dart FFI 内存管理:用 using + Arena 替代嵌套 try-finally
前端·flutter