[Flutter3] 记录Dio的简单封装(一)

文章目录

效果

请求成功/失败/异常的日志输出效果

成功:

失败:500

失败:404

网络异常:

使用

举个使用的例子, 在调用 DioManager的时候, 直接通过返回值的状态, 来处理各个情况,不用在 try{}catch{}里面各写一遍处理逻辑,

比如上图,就是直接调用的封装的API

dart 复制代码
      ResponseEntity res = await DioManager().requestGet(HttpApi.user_record, param: {
        "openid": "okqbz5K-4UoymmukFtxyQAyImKm0",
        "uid": "88030",
        "subject": '20',
        "unionid": "ofJJv6M45ChFhuUZyVaLXwt07M4g",
      });
      res.toLog();

直接同步获取了请求的结果,通过 ResponseEntity 来处理本次请求的各项情况(如上4图)

ResponseEntity类

提供了 泛型T的data属性,

提供了 tag, 用于处理请求的不同情况

提供了 toString/ toLog函数 , 用于查看请求/返回/状态码/请求参数等

dart 复制代码
class ResponseEntity<T> {
  /// 常规的response.data的返回字段
  late String? msg;
  late int? code;
  T? data;

  /// response.data中,自定以追加的一些字段(方便日志查看)
  late int? tag; // 业务tag  0=>通信OK+业务未跑通 1=>通信OK+业务跑通  2=>通信失败(各类原因...) 9=>解析/socket等异常
  late String? method; // 请求的 method
  late String? baseUrl; // 请求的host地址 - 方便打印日子产看环境
  late String? path; // 请求地址
  late String? desc; // 自定义的报文描述-便于判断请求情况
  late Map<String, dynamic>? queryParameters; // 请求的参数

  ResponseEntity(
      this.code, this.msg, this.data, this.tag, this.method, this.baseUrl, this.path, this.desc, this.queryParameters);

  ResponseEntity.initFromJson(Map<String, dynamic> jsonMap) {
    code = jsonMap.containsKey(ConstantUtil.code) ? jsonMap[ConstantUtil.code] as int? : 0;
    msg = jsonMap.containsKey(ConstantUtil.msg) ? jsonMap[ConstantUtil.msg] as String? : "";
    // 存在data
    if (jsonMap.containsKey(ConstantUtil.data)) {
      data = jsonMap[ConstantUtil.data] as T;
    }

    /// response自定以追加的一些字段处理
    tag = jsonMap.containsKey(ConstantUtil.tag) ? jsonMap[ConstantUtil.tag] : 9;
    method = jsonMap.containsKey(ConstantUtil.method) ? jsonMap[ConstantUtil.method] : "";
    baseUrl = jsonMap.containsKey(ConstantUtil.baseUrl) ? jsonMap[ConstantUtil.baseUrl] : "";
    path = jsonMap.containsKey(ConstantUtil.path) ? jsonMap[ConstantUtil.path] : "";
    queryParameters = jsonMap.containsKey(ConstantUtil.queryParameters) ? jsonMap[ConstantUtil.queryParameters] : null;
    desc = jsonMap.containsKey(ConstantUtil.desc) ? jsonMap[ConstantUtil.desc] : "";
  }

  /// 手动重写toString 方法,方便查看日志
  @override
  String toString() {
    var _code = "code:$code\n";
    var _msg = "msg:$msg\n";
    var _data = json.encode(data).toString();
    var _dataString = "data:$_data\n";
    var _tag = "tag:$tag\n";
    var _method = "method:$method\n";
    var _baseUrl = "baseUrl:$baseUrl\n";
    var _path = "path:$path\n";
    var _desc = "path:$desc\n";
    var _queryParameters = jsonEncode(queryParameters);
    var _queryParametersString = "queryParameters:$_queryParameters\n";

    return _code + _msg + _dataString + _tag + _method + _baseUrl + _path + _desc + _queryParametersString;
  }

  /// 提供自带的打印函数
  void toLog() {
    LoggerUtil().d(toString());
  }
}

DioManager封装

对DioManager进行单例模式处理

dart 复制代码
  /// dio管理类的单例的实现 --------------------------------------------------
  // 定义私有管理对象 _singleton
  static final DioManager _singleton = DioManager._();

  // 私有对象构造实现
  DioManager._() {
    // dio初始化 - 配置全局options - 具体事项先省略
  }

  // 声明并完成初始化的私有变量(_singleton),
  // 通过 DioManager的工厂函数(factory关键字) ,进行单例模式返回
  factory DioManager() => _singleton;

提供_request通用方法

dart 复制代码
 /// request 通用处理函数 -----------------------------------------------------------
  /// get 对应的是 queryParam
  /// post 对应的是 data
  /// 通过 对 try/catch 的处理, 均异步返回有效的 BaseResponseEntity<T> 实例,
  /// 外部调用时候,仅获取数据是, 可以不必包裹 try/catch,
  Future<ResponseEntity<T>> _request<T>(
    String method,
    String apiPath, {
    Map<String, dynamic>? param,
    CancelToken? cancelToken,
    Options? options,
  }) async {
    try {
      // 通用请求
      Response<dynamic> response = await _dio.request(apiPath,
          data: param, queryParameters: param, cancelToken: cancelToken, options: _loadOptions(method, options));
      // 通过 _onResponse()函数转换response
      // 自定义返回的data内容, 除了原有的 code/msg/data信息, 新增desc/tag等返回数据
      response = _onResponse(response);
      return ResponseEntity<T>.initFromJson(response.data);
    } on DioException catch (err) {
      // 通过对DioException的解析,返回自定义的BaseResponseEntity实例
      return _onDioException(err) as ResponseEntity<T>;
    }

  }

_onResponse / _onDioException 的设计

根据Request的情况, 把交互场景分为了四类

1&2: statusCode == 200 , 再区分业务code是否OK

3: statusCode !==200, 可能是 404 /500 等情况

4: 断网等异常情况

其中 1&2&3, 都是通过_onResponse处理

4通过_onDioException处理, 这里的catch不再直接抛出, 用ResponseEntity来统一做返回格式处理

(DioException)

Response的处理

dart 复制代码
class ResponseEntity<T> {
  /// 常规的response.data的返回字段
  late String? msg;
  late int? code;
  T? data;

  /// response.data中,自定以追加的一些字段(方便日志查看)
  late int? tag; // 业务tag  0=>通信OK+业务未跑通 1=>通信OK+业务跑通  2=>通信失败(各类原因...) 9=>解析/socket等异常
  late String? method; // 请求的 method
  late String? baseUrl; // 请求的host地址 - 方便打印日子产看环境
  late String? path; // 请求地址
  late String? desc; // 自定义的报文描述-便于判断请求情况
  late Map<String, dynamic>? queryParameters; // 请求的参数

  ResponseEntity(
      this.code, this.msg, this.data, this.tag, this.method, this.baseUrl, this.path, this.desc, this.queryParameters);

  ResponseEntity.initFromJson(Map<String, dynamic> jsonMap) {
    code = jsonMap.containsKey(ConstantUtil.code) ? jsonMap[ConstantUtil.code] as int? : 0;
    msg = jsonMap.containsKey(ConstantUtil.msg) ? jsonMap[ConstantUtil.msg] as String? : "";
    // 存在data
    if (jsonMap.containsKey(ConstantUtil.data)) {
      data = jsonMap[ConstantUtil.data] as T;
    }

    /// response自定以追加的一些字段处理
    tag = jsonMap.containsKey(ConstantUtil.tag) ? jsonMap[ConstantUtil.tag] : 9;
    method = jsonMap.containsKey(ConstantUtil.method) ? jsonMap[ConstantUtil.method] : "";
    baseUrl = jsonMap.containsKey(ConstantUtil.baseUrl) ? jsonMap[ConstantUtil.baseUrl] : "";
    path = jsonMap.containsKey(ConstantUtil.path) ? jsonMap[ConstantUtil.path] : "";
    queryParameters = jsonMap.containsKey(ConstantUtil.queryParameters) ? jsonMap[ConstantUtil.queryParameters] : null;
    desc = jsonMap.containsKey(ConstantUtil.desc) ? jsonMap[ConstantUtil.desc] : "";
  }

  /// 手动重写toString 方法,方便查看日志
  @override
  String toString() {
    var _code = "code:$code\n";
    var _msg = "msg:$msg\n";
    var _data = json.encode(data).toString();
    var _dataString = "data:$_data\n";
    var _tag = "tag:$tag\n";
    var _method = "method:$method\n";
    var _baseUrl = "baseUrl:$baseUrl\n";
    var _path = "path:$path\n";
    var _desc = "path:$desc\n";
    var _queryParameters = jsonEncode(queryParameters);
    var _queryParametersString = "queryParameters:$_queryParameters\n";

    return _code + _msg + _dataString + _tag + _method + _baseUrl + _path + _desc + _queryParametersString;
  }

  /// 提供自带的打印函数
  void toLog() {
    LoggerUtil().d(toString());
  }
}

catch处理

dart 复制代码
  /// 对 DioException进行解析,基本覆盖大部分错误类型了
  ResponseEntity _onDioException(DioException err) {
    var errType = err.type;
    var path = err.requestOptions.path;
    var data = err.requestOptions.data;
    var queryParameters = err.requestOptions.queryParameters;
    var baseUrl = err.requestOptions.baseUrl;
    var method = err.requestOptions.method;

    ResponseEntity baseResponseEntity = ResponseEntity(0, "", data, 9, method, baseUrl, path, "", queryParameters);

    ///连接超时
    if (errType == DioExceptionType.connectionTimeout) {
      baseResponseEntity.msg = "连接超时";
      baseResponseEntity.desc = "连接超时";
    }

    ///发送超时
    if (errType == DioExceptionType.sendTimeout) {
      baseResponseEntity.msg = "发送超时";
      baseResponseEntity.desc = "发送超时";
    }

    ///接收超时
    if (errType == DioExceptionType.receiveTimeout) {
      baseResponseEntity.msg = "接收超时";
      baseResponseEntity.desc = "接收超时";
    }

    ///证书损坏
    if (errType == DioExceptionType.badCertificate) {
      baseResponseEntity.msg = "证书损坏";
      baseResponseEntity.desc = "证书损坏";
    }

    ///返回内容问题
    if (errType == DioExceptionType.badResponse) {
      baseResponseEntity.msg = "返回内容问题";
      baseResponseEntity.desc = "返回内容问题";
    }

    ///请求取消
    if (errType == DioExceptionType.cancel) {
      baseResponseEntity.msg = "请求取消";
      baseResponseEntity.desc = "请求取消";
    }

    ///连接错误-无网络
    if (errType == DioExceptionType.connectionError) {
      baseResponseEntity.msg = "连接错误-无网络";
      baseResponseEntity.desc = "连接错误-无网络";
    }

    ///未知错误
    if (errType == DioExceptionType.unknown) {
      baseResponseEntity.msg = "未知错误";
      baseResponseEntity.desc = "未知错误";
    }
    return baseResponseEntity;
  }

针对ResponseEntity中, T? data 的处理, 稍后补上, 先走通请求...

--- 数据转模型看这个
[Flutter3] Json转dart模型举例

对于泛型T的处理, 直接把 json转model的model类型传入泛型就可获取数据

相关推荐
JaguarJack2 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo2 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack1 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理2 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1232 天前
matlab画图工具
开发语言·matlab
dustcell.2 天前
haproxy七层代理
java·开发语言·前端
norlan_jame2 天前
C-PHY与D-PHY差异
c语言·开发语言
多恩Stone2 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
QQ4022054962 天前
Python+django+vue3预制菜半成品配菜平台
开发语言·python·django
QQ5110082852 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php