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

文章目录

  • 效果
  • 使用
  • ResponseEntity类
  • DioManager封装
    • _onResponse / _onDioException 的设计
    • Response的处理
    • catch处理

效果

请求成功/失败/异常的日志输出效果
成功:
在这里插入图片描述
失败:500
在这里插入图片描述
失败:404
在这里插入图片描述
网络异常:
在这里插入图片描述

使用

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

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

      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函数 , 用于查看请求/返回/状态码/请求参数等


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 方法,方便查看日志
  
  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进行单例模式处理

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

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

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

提供_request通用方法

 /// 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的处理

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 方法,方便查看日志
  
  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处理

  /// 对 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类型传入泛型就可获取数据

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/574795.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ESP32开发WebSocket报错TRANSPORT_WS: Sec-WebSocket-Accept not found

我的芯片是ESP32-S3&#xff0c;用ESP-IDF框架进行开发的时候&#xff0c;用官方的WebSocket的example创建了项目。然后把WebSocket连接uri替换为自己的服务器后&#xff0c;运行到esp_websocket_client_start开始连接后&#xff0c;直接报错&#xff1a; E (10615) TRANSPORT…

网络爬虫之爬虫原理

** 爬虫概述 Python网络爬虫是利用Python编程语言编写的程序&#xff0c;通过互联网爬取特定网站的信息&#xff0c;并将其保存到本地计算机或数据库中。 """ 批量爬取各城市房价走势涨幅top10和跌幅top10 """ ​ from lxml import etree impor…

AJAX——黑马头条-数据管理平台项目

1.项目介绍 功能&#xff1a; 登录和权限判断查看文章内容列表&#xff08;筛选&#xff0c;分页&#xff09;编辑文章&#xff08;数据回显&#xff09;删除文章发布文章&#xff08;图片上传&#xff0c;富文本编辑器&#xff09; 2.项目准备 技术&#xff1a; 基于Bootst…

【韩国】UE5的MetaHuman确实可以导入Blender进行编辑。

UE5的MetaHuman确实可以导入Blender进行编辑。根据网络上的信息&#xff0c;你可以将MetaHuman模型导出为FBX文件&#xff0c;然后在Blender中进行修改。修改完成后&#xff0c;你可以将其重新导入到Unreal Engine 5中4。请注意&#xff0c;当你在Blender中编辑模型时&#xff…

第12章 最佳的UI体验——Material Design实战

第12章 最佳的UI体验——Material Design实战 其实长久以来&#xff0c;大多数人都认为Android系统的UI并不算美观&#xff0c;至少没有iOS系统的美观。以至于很多IT公司在进行应用界面设计的时候&#xff0c;为了保证双平台的统一性&#xff0c;强制要求Android端的界面风格必…

使用Shell终端访问Linux

一、实验目的 1、熟悉Linux文件系统访问命令&#xff1b; 2、熟悉常用 Linux Shell的命令&#xff1b; 3、熟悉在Linux文件系统中vi编辑器的使用&#xff1b; 4、进一步熟悉虚拟机网络连接模式与参数配置&#xff01; 二、实验内容 1、使用root帐号登陆到Linux的X-windows…

artifactory配置docker本地存储库

​一、概述 本地 Docker 存储库是我们部署和托管内部 Docker 镜像的位置。实际上&#xff0c;它是一个 Docker 注册表&#xff0c;能够托管的 Docker 镜像的集合。通过本地存储库&#xff0c;你可以保存、加载、共享和管理自己的 Docker 镜像&#xff0c;而无需依赖于外部的镜像…

API提取IP

API代理作为IP代理的一项重要业务&#xff0c;在绕开地域网络限制&#xff0c;提高作业效率等方面提供强大的技术支持。它能够帮助用户快速实现软件与软件间的交流&#xff0c;无障碍连通不同应用程序逻辑开发的系统应用。API代理用途范围广泛&#xff0c;如使用API提取代理IP、…

AcWing 1264. 动态求连续区间和 ,详细讲解线段树与树状数组(Python,篇一)

本篇博客主要介绍一下什么是线段树与树状数组&#xff0c;它们的原理与结构是怎样&#xff0c;并通过实际题型来讲解&#xff0c;篇一主要讲解线段树&#xff0c;下一篇博客讲解树状数组。 线段树与树状数组的区别和特点&#xff1a; 它们的时间复杂度都是O(nlogn) 存储方式…

使用navicate演示在 PostgreSQL 中使用 for 循环语句

1、简单循环示例 do $$ beginfor cnt in 1..10 loopraise notice cnt: %, cnt;end loop; end; $$ navicate中执行 2、循环查询 do $$ declare_record record; beginfor _record in (SELECT version,description FROM flyway_schema_history ORDER BY installed_rank desc li…

ios CI/CD 持续集成 组件化专题一 iOS 将图片打包成bundle

一、 创建 选择 macos 下的Bundle 二 、取名点击下一步 三、Base SDK 选择ios 四 、Build Active Architecture Only 五、Installation后面的内容删除 六、Skip Install 选择NO 七、Strip Debug Symbols During Copy 中"Release"项设置为 "YES" 八、COM…

书生·浦语 大模型(学习笔记-7)LMDeploy 量化部署 LLM-VLM 实践

目录 一、模型的部署 二、模型部署面临的问题 三、如何解决&#xff08;两种方法&#xff09; 四、LMDeploy相关知识 创建conda环境(漫长的等待) 五、使用LMDeploy与模型对话 六、设置最大KV Cache缓存大小 七、W4A16量化 八、客户端连接API服务器 一、模型的部署 二、…

leetcode-二叉树的镜像-91

题目要求 思路1 1.遍历一遍二叉树&#xff0c;将左边的结点对应创建一个右边的结点 2.用此方法空间复杂度O(n)&#xff0c;并不是最优 思路2 1.将一个结点的左右子树进行交换&#xff0c;如果左子树还有左右结点&#xff0c;就再交换左子树的左右结点&#xff0c;以此递归下去…

【树莓派】yolov5 Lite,目标检测,行人检测入侵报警

延续之前的程序&#xff1a; https://qq742971636.blog.csdn.net/article/details/138172400 文章目录 播放声音pygame不出声音怎么办&#xff08;调节音量&#xff09;树莓派上的音乐播放器&#xff08;可选&#xff09;命令行直接放歌&#xff08;尝试放mp3歌曲&#xff09; …

linux 上 jps 列出一堆 jar,如何快速定位 jar 文件启动位置?

例如&#xff0c;在 /data下有一个 xxx.jar &#xff0c;如果是通过 "java -jar /data/xxx.jar" 方式启动&#xff0c;则 jps会列出的名字中带 xxx.jar&#xff0c;这时再 "ps -ef | grep xxx.jar" 就会列出 更详细的信息&#xff0c;例如 "java -ja…

[iOS]CocoaPods安装和使用

1.了解brew、rvm、ruby、gem、cocaspods之间的关系 在 macOS 环境中&#xff0c;Brew、RVM、Ruby、Gem 和 CocoaPods 之间存在以下关系&#xff1a; Homebrew (Brew)&#xff1a;Homebrew 是 macOS 上的包管理器&#xff0c;用于安装和管理各种开源软件包。它使您能够轻松地从…

Windows 本地直接使用 SSH,SFTP 以及 SFTP下载文件到 Windows/mac 本地或上传(没有客户端时)

windows 本地打开 ssh 以及 sftp 等的方式 1.win(windows图标那个键) r 直接搜 然后从打开的位置运行 如果是打开 sftp 前面的 ssh 换一下成sftp 就行 直接从地址栏输入也可以直接转过去 通过 windows 的工具直接访问 sftp 后将文件下载到自己的windows 或 mac 上 先通过…

微软在汉诺威工业博览会上推出新制造业Copilot人工智能功能,强化Dynamics 365工具集

在近日于德国汉诺威举行的盛大工业博览会上&#xff0c;微软向全球展示了其最新推出的制造业人工智能功能&#xff0c;这些功能以Dynamics 365工具集为核心&#xff0c;旨在通过先进的AI技术为制造业带来前所未有的变革。 此次推出的新功能中&#xff0c;最为亮眼的是支持AI的…

Linux之ebpf(1)基础使用

Linux之ebpf(1)基础使用 Author: Once Day Date: 2024年4月20日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可以参考专栏&#xff1a;Linux基础知识_Once-D…

Linux系统网络---DNS域名解析服务

目录 一、DNS的简介 DNS系统的分布式数据结构&#x1f447; DNS系统类 两种查询方式 二.正向解析实验 1.先关闭防火墙、selinux 2.安装bind 3.查看配置、修改配置 4.修改区域配置文件 正向解析&#x1f447; 反向解析&#x1f447; 5.修改 正向解析&#x1f…