• Flutter完整的Dio网络框架null空安全二次封装。


    所需依赖添加在项目中的pubspec.yaml中:
    
    dio: ^4.0.6                                       #网络请求
    connectivity_plus: ^2.3.6                         #网络监测
    pretty_dio_logger: ^1.1.1                         #日志打印
    class HttpRequest {
      // 单例模式使用Http类,
      static final HttpRequest _instance = HttpRequest._internal();
    
      factory HttpRequest() => _instance;
    
      static late final Dio dio;
    
      /// 内部构造方法
      HttpRequest._internal() {
        /// 初始化dio
        BaseOptions options = BaseOptions(
            connectTimeout: HttpOptions.connectTimeout,
            receiveTimeout: HttpOptions.receiveTimeout,
            sendTimeout: HttpOptions.sendTimeout,
            baseUrl: HttpOptions.baseUrl);
        dio = Dio(options);
    
        /// 添加各种拦截器
        dio.interceptors.add(ErrorInterceptor());
        dio.interceptors.add(PrettyDioLogger(
            requestHeader: true,
            requestBody: true,
            responseHeader: true,
            responseBody: true));
      }
    
      /// 封装request方法
      Future request({
        required String path,
        required HttpMethod method,
        dynamic data,
        Map? queryParameters,
        bool showLoading = true,
        bool showErrorMessage = true,
      }) async {
        const Map methodValues = {
          HttpMethod.get: 'get',
          HttpMethod.post: 'post',
          HttpMethod.put: 'put',
          HttpMethod.delete: 'delete',
          HttpMethod.patch: 'patch',
          HttpMethod.head: 'head'
        };
    
        //动态添加header头
        Map headers = Map();
        headers["version"] = "1.0.0";
     
    
        Options options = Options(
          method: methodValues[method],
          headers: headers,
        );
    
        try {
          if (showLoading) {
            EasyLoading.show(status: 'loading...');
          }
          Response response = await HttpRequest.dio.request(
            path,
            data: data,
            queryParameters: queryParameters,
            options: options,
          );
          return response.data;
        } on DioError catch (error) {
          HttpException httpException = error.error;
          if (showErrorMessage) {
            EasyLoading.showToast(httpException.msg);
          }
        } finally {
          if (showLoading) {
            EasyLoading.dismiss();
          }
        }
      }
    }
    
    enum HttpMethod {
      get,
      post,
      delete,
      put,
      patch,
      head,
    }

    class ErrorInterceptor extends Interceptor {
      @override
      void onError(DioError err, ErrorInterceptorHandler handler) async {
        /// 根据DioError创建HttpException
        HttpException httpException = HttpException.create(err);
    
        /// dio默认的错误实例,如果是没有网络,只能得到一个未知错误,无法精准的得知是否是无网络的情况
        /// 这里对于断网的情况,给一个特殊的code和msg
        if (err.type == DioErrorType.other) {
          var connectivityResult = await (Connectivity().checkConnectivity());
          if (connectivityResult == ConnectivityResult.none) {
            httpException = HttpException(code: -100, msg: 'None Network.');
          }
        }
    
        /// 将自定义的HttpException
        err.error = httpException;
    
        /// 调用父类,回到dio框架
        super.onError(err, handler);
      }
    }

    class HttpException implements Exception {
      final int code;
      final String msg;
    
      HttpException({
        this.code = -1,
        this.msg = 'unknow error',
      });
    
      @override
      String toString() {
        return 'Http Error [$code]: $msg';
      }
    
      factory HttpException.create(DioError error) {
        /// dio异常
        switch (error.type) {
          case DioErrorType.cancel:
            {
              return HttpException(code: -1, msg: 'request cancel');
            }
          case DioErrorType.connectTimeout:
            {
              return HttpException(code: -1, msg: 'connect timeout');
            }
          case DioErrorType.sendTimeout:
            {
              return HttpException(code: -1, msg: 'send timeout');
            }
          case DioErrorType.receiveTimeout:
            {
              return HttpException(code: -1, msg: 'receive timeout');
            }
          case DioErrorType.response:
            {
              try {
                int statusCode = error.response?.statusCode ?? 0;
                // String errMsg = error.response.statusMessage;
                // return ErrorEntity(code: errCode, message: errMsg);
                switch (statusCode) {
                  case 400:
                    {
                      return HttpException(code: statusCode, msg: 'Request syntax error');
                    }
                  case 401:
                    {
                      return HttpException(code: statusCode, msg: 'Without permission');
                    }
                  case 403:
                    {
                      return HttpException(code: statusCode, msg: 'Server rejects execution');
                    }
                  case 404:
                    {
                      return HttpException(code: statusCode, msg: 'Unable to connect to server');
                    }
                  case 405:
                    {
                      return HttpException(code: statusCode, msg: 'The request method is disabled');
                    }
                  case 500:
                    {
                      return HttpException(code: statusCode, msg: 'Server internal error');
                    }
                  case 502:
                    {
                      return HttpException(code: statusCode, msg: 'Invalid request');
                    }
                  case 503:
                    {
                      return HttpException(code: statusCode, msg: 'The server is down.');
                    }
                  case 505:
                    {
                      return HttpException(code: statusCode, msg: 'HTTP requests are not supported');
                    }
                  default:
                    {
                      return HttpException(
                          code: statusCode, msg: error.response?.statusMessage ?? 'unknow error');
                    }
                }
              } on Exception catch (_) {
                return HttpException(code: -1, msg: 'unknow error');
              }
            }
          default:
            {
              return HttpException(code: -1, msg: error.message);
            }
        }
      }
    }

    class HttpOptions {
      /// 超时时间;单位是ms
      static const int connectTimeout = 15000;
      static const int receiveTimeout = 15000;
      static const int sendTimeout = 15000;
    
      /// 地址域名前缀
      static const String baseUrl = '************';
    
    }

    /// 调用底层的request,重新提供get,post等方便方法
    class HttpUtils {
      static HttpRequest httpRequest = HttpRequest();
    
      /// get
      static Future get({
        required String path,
        Map? queryParameters,
        bool showLoading = true,
        bool showErrorMessage = true,
      }) {
        return httpRequest.request(
          path: path,
          method: HttpMethod.get,
          queryParameters: queryParameters,
          showLoading: showLoading,
          showErrorMessage: showErrorMessage,
        );
      }
    
      /// post
      static Future post({
        required String path,
        required HttpMethod method,
        dynamic data,
        bool showLoading = true,
        bool showErrorMessage = true,
      }) {
        return httpRequest.request(
          path: path,
          method: HttpMethod.post,
          data: data,
          showLoading: showLoading,
          showErrorMessage: showErrorMessage,
        );
      }
    
    }
  • 相关阅读:
    详解如何快速查询Node.js版本信息(六种方法)
    第10章 PCA降维技术
    idea2023开发插件入门
    智能汽车能否真正实现无人驾驶,为什么?
    数据库 基础面试第一弹
    信息学奥赛一本通:1003:对齐输出
    JavaWeb基础学习Servlet
    fast guide filter原理详解
    Java 数据结构篇-实现单链表核心API
    基于Git和Jenkins企业级自动化测试及部署实例,附详细截图和完整代码
  • 原文地址:https://blog.csdn.net/fangShiKang/article/details/127882096