Dio https://github.com/flutterchina/dio 是一个强大的 Dart Http 请求库, 支持 Restful API,FormData, 拦截器, 请求取消, Cookie 管理, 文件上传 / 下载, 超时, 自定义适配器等. 目前 Dio 在 https://pub.dartlang.org/packages/dio 上综合得分 100 分, 排名已上榜 pub 首页(All Tab 下) ! 同时 Dio 也是 GitHub 上最受欢迎的 Flutter 第三方库, 项目地址: Dio-GitHub https://github.com/flutterchina/dio/issues .
从 1.0 发布至今, Dio 受到了大量国内外开发者的关注, 并收到了很多肯定和建议. 为了让 Dio 功能更强大, 让开发者使用起来更容易, 我们综合了 1.0 中的各种反馈, 对 Dio 进行了一次大的更新, 为了让使用者在 1.0 和 2.x 之间有个过渡, 我们将 2.0.x-2.1.0 作为预发布版在全网进行了接近两个月的公测. 现在, 很高兴的告诉大家, 2.x 的功能已经收敛, 质量已经稳定, 因此, 今天我们正式发布 Dio 2.x 的第一个稳定版 Dio v2.1.0 https://github.com/flutterchina/dio .
相比 1.x,2.x 在 Restful API, 拦截器, FormData 等很多地方都进行了扩展和调整, 除了这些, Dio 在 2.x 中还引入 Adapter 层, 为 Mock 接口数据和自定义底层网络库提供了支持. 整体功能相比 1.x 有了很大的提升, 因此我们强烈建议所有 1.x 用户都能升级到 2.1.
Dio V2.1.x 变更列表
Restful API
2.1 中对所有 Restful API 的变化有:
支持 Uri, 在 1.x 中, Url 只能是字符串, 2.1 中所有 API 都提供了对应支持 Uri 的版本, 如 get 方法有 dio.get(...)和 dio.gerUri(...).
所有方法都支持 queryParameters,2.1 标准化了参数语义, 并允许所有请求都可以传 query, 而 data 只针对可以提交请求体的方法如 post 作为请求体提交. 另外相对于 Uri.queryParameters, 我们对 Restful API 中的 queryParameters 的功能做了加强, 主要有两个差异:
参数值类型不同; 前者只能接受 Map<String, String|Iterable<String>>类型的参数, 而后者可以接受 Map<String, dynamic > 类型, 比如:
- dio.getUri(Uri(url, queryParameters: {
- "age":15
- })) // 会抛出异常, Uri.queryParameter 的 value 不能是 int 类型
- dio.get(url, queryParameters: {
- "age":15
- }); // 这是 OK 的!
编码方式有所差异; Uri.queryParameters 编码方式遵循 Dart SDK 中的规则, 而 Restful API 中的 queryParameters 编码方式和 jQuery 一致, 如:
- dio.options.baseUrl="http://domain.com/";
- // 下面请求的最终 uri 为: http://domain.com/api?selectedId=1&selectedId=2
- Response response = await dio.getUri(
- Uri(path: "api",queryParameters: {"selectedId": ["1", "2"],});
- );
- // 下面请求的最终 uri 为: https://flutterchina.club?selectedId[]=1&selectedId[]=2
- dio.get("api",queryParameters: {"selectedId": ["1", "2"], });
支持以 Stream 方式提交数据了; 2.1 中可以通过 Stream 的方式来提交二进制数据了, 详细的示例可以参考这里.
支持以二进制数组形式接收数据了; 1.x 中如果要以二进制形式接收响应数据则需要设置 options.responseType 为 ResponseType.stream 来接收响应流, 然后再通过读取响应流来获取完整的二进制内容, 而 2.x 中只需要设置为 ResponseType.bytes, 则可直接获得响应流的而精致数组.
API 统一添加了 onSendProgress 和 onReceiveProgress 两个回调, 用于监听发送数据和接收数据的具体精度, 在 1.x 中只有在下载文件和上传 formdata 时才能监听进度, 而 2.x 中所有接口都可以了.
拦截器
支持设置多个拦截器;
这样我们就可以将一些功能单独抽离, 比如打印请求 / 响应日志和 cookie 管理都可以单独封装在一个拦截器中, 这样在解耦的同时可以提高代码的可复用度.
2.1 中拦截器是一个队列, 拦截器将会按照 FIFO 顺序执行, 如果队列中的某个拦截器返回了 Response 或 Error, 则请求结束, 队列后面的拦截器将不会再被执行.
预置了打印请求 / 响应日志的 LogInterceptor 和管理 cookie 的 CookieManager 拦截器, 开发者可以按需使用, 如:
- dio.interceptors
- ..add(LogInterceptor(responseBody: false))
- ..add(CookieManager(CookieJar()));
FormData
1.x 中, 在提交 FormData 时会先将 FormData 转成一个二进制数组, 然后再提交, 这在 FormData 中的数据量比较大时 (如包含多个大文件) 在上传的过程中会比较占用内存. 2.1 中我们队 FormData 进行了增强, 给 FormData 添加一个 stream 属性, 它可以将 FormData 转为一个 stream, 在提交时无需一次性加载到内存.
同时 FormData 也添加了 asBytes() ,asBytesAsync(),length 等方法, 属性.
Response
Response 中添加了一些关于重定向信息的字段, 有 isRedirect,redirects,realUri.
TransFormer
2.x 中对于 DefaultTransformer 添加了一个 jsonDecodeCallback, 通过它可以定制 JSON 解码器, 这在 flutter 中非常有用, 我们可以通过 compute 方法来在后台进行 JSON 解码, 从而避免在 UI 线程对复杂 JSON 解码时引起的界面卡顿, 详情请见这里 https://github.com/flutterchina/dio#in-flutter .
HttpClientAdapter
HttpClientAdapter 是 Dio 和 HttpClient 之间的桥梁. 2.0 抽象出了 adapter 层, 可以带来两个主要收益:
实现 Dio 于 HttpClient 的解耦, 这样可以方便的切换, 定制底层网络库.
可以 Mock 数据;
Dio 实现了一套标准的, 强大 API, 而 HttpClient 则是真正发起 Http 请求的对象, 两者并不是固定的一对一关系, 我们完全可以在使用 Dio 时通过其他网络库 (而不仅仅是 dart HttpClient ) 来发起网络请求. 我们通过 HttpClientAdapter 将 Dio 和 HttpClient 解耦, 这样一来便可以自由定制 Http 请求的底层实现, 比如, 在 Flutter 中我们可以通过自定义 HttpClientAdapter 将 Http 请求转发到 Native 中, 然后再由 Native 统一发起请求. 再比如, 假如有一天 OKHttp 提供了 dart 版, 你想使用 OKHttp 发起 http 请求, 那么你便可以通过适配器来无缝切换到 OKHttp, 而不用改之前的代码.
Dio 使用 DefaultHttpClientAdapter 作为其默认 HttpClientAdapter,DefaultHttpClientAdapter 使用 dart:io:HttpClient 来发起网络请求.
这里 有一个简单的自定义 Adapter 的示例, 读者可以参考. 另外本项目的自动化测试用例全都是通过一个自定义的 MockAdapter 来模拟服务器返回数据的.
Options
Options 对象包含了对网络请求的配置, 在 1.x 中无论是实例配置还是单次请求的配置都使用的是 Options 对象, 这样会带来一些二义性, 甚至有时会让开发者感到疑惑, 比如 Options.baseUrl 属性代表请求基地址, 理论上它只应该在实例配置中设置, 而不应该出现在每次请求的配置中; 再比如 Options.path 属性, 它代表请求的相对路径, 不应该在实例请求配置中. 2.1 中将请求配置分拆成三个类:
类名 | 作用 |
---|---|
BaseOptions | Dio 实例基配置,默认对该 dio 实例的所有请求生效 |
Options | 单次请求配置,可以覆盖 BaseOptions 中的同名属性 |
RequestOptions | 请求的最终配置,是对 Option 和 BaseOptions 合并后的 |
另外, 添加了一些新的配置项:
cookies: 可以添加一些公共 cookie
receiveDataWhenStatusError
: 当响应状态码不是成功状态 (如 404) 时, 是否接收响应内容, 如果是 false, 则 response.data 将会为 null
maxRedirects: 重定向最大次数.
来源: https://juejin.im/post/5c871b256fb9a049bb7d2c32