dio
dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等…
添加依赖
1 | dependencies: |
一个极简的示例
1 | import 'package:dio/dio.dart'; |
内容列表
- 示例
- Dio APIs
- 请求配置
- 响应数据
- 拦截器
- 错误处理
- 使用application/x-www-form-urlencoded编码
- FormData
- 转换器
- 设置Http代理
- Https证书校验
- 请求取消
- Cookie管理
- Features and bugs
示例
发起一个 GET
请求 :
1 | Response response; |
发起一个 POST
请求:
1 | response = await dio.post("/test", data: {"id": 12, "name": "wendu"}); |
发起多个并发请求:
1 | response = await Future.wait([dio.post("/info"), dio.get("/token")]); |
下载文件:
1 | response = await dio.download("https://www.google.com/", "./xx.html"); |
发送 FormData:
1 | FormData formData = new FormData.from({ |
通过FormData上传多个文件:
1 | FormData formData = new FormData.from({ |
监听发送(上传)数据进度:
1 | response = await dio.post( |
…你可以在这里获取所有示例代码.
Dio APIs
创建一个Dio实例,并配置它
你可以使用默认配置或传递一个可选 Options
参数来创建一个Dio实例 :
1 | Dio dio = new Dio; // 使用默认配置 |
Dio实例的核心API是 :
Future
1 | response = await request( |
请求方法别名
为了方便使用,Dio提供了一些其它的Restful API, 这些API都是request
的别名。
Future
Future
Future
Future
Future
Future
Future
Future
{OnDownloadProgress onProgress, data, bool flush: false, Options options,CancelToken cancelToken})
请求配置
下面是所有的请求配置选项。 如果请求method
没有指定,则默认为GET
:
1 | { |
这里有一个完成的示例.
响应数据
当请求成功时会返回一个Response对象,它包含如下字段:
1 | { |
示例如下:
1 | Response response = await dio.get("https://www.google.com"); |
拦截器
每一个 Dio 实例都有一个请求拦截器 RequestInterceptor
和一个响应拦截器 ResponseInterceptor
, 通过拦截器你可以在请求之前或响应之后(但还没有被 then
或 catchError
处理)做一些统一的预处理操作。
1 | dio.interceptor.request.onSend = (Options options){ |
如果你想移除拦截器,你可以将它们置为null:
1 | dio.interceptor.request.onSend = null; |
完成和终止请求/响应
在所有拦截器中,你都可以改变请求执行流, 如果你想完成请求/响应并返回自定义数据,你可以返回一个 Response
对象或返回 dio.resolve(data)
的结果。 如果你想终止(触发一个错误,上层catchError
会被调用)一个请求/响应,那么可以返回一个DioError
对象或返回 dio.reject(errMsg)
的结果.
1 | dio.interceptor.request.onSend = (Options options) { |
拦截器中支持异步任务
拦截器中不仅支持同步任务,而且也支持异步任务, 下面是在请求拦截器中发起异步任务的一个实例:
1 | dio.interceptor.request.onSend = (Options options) async { |
Lock/unlock 拦截器
你可以通过调用拦截器的 lock()
/unlock
方法来锁定/解锁拦截器。一旦请求/响应拦截器被锁定,接下来的请求/响应将会在进入请求/响应拦截器之前排队等待,直到解锁后,这些入队的请求才会继续执行(进入拦截器)。这在一些需要串行化请求/响应的场景中非常实用,后面我们将给出一个示例。
1 | tokenDio = new Dio(); //Create a new instance to request the token. |
Clear()
你也可以调用拦截器的clear()
方法来清空等待队列。
别名
当请求拦截器被锁定时,接下来的请求将会暂停,这等价于锁住了dio实例,因此,Dio示例上提供了请求拦截器lock/unlock
的别名方法:
dio.lock() == dio.interceptor.request.lock()
dio.unlock() == dio.interceptor.request.unlock()
dio.clear() == dio.interceptor.request.clear()
示例
假设这么一个场景:出于安全原因,我们需要给所有的请求头中添加一个csrfToken,如果csrfToken不存在,我们先去请求csrfToken,获取到csrfToken后,再发起后续请求。 由于请求csrfToken的过程是异步的,我们需要在请求过程中锁定后续请求(因为它们需要csrfToken), 直到csrfToken请求成功后,再解锁,代码如下:
1 | dio.interceptor.request.onSend = (Options options) { |
完整的示例代码请点击 这里.
错误处理
当请求过程中发生错误时, Dio 会包装 Error/Exception
为一个 DioError
:
1 | try { |
DioError 字段
1 | { |
DioErrorType
1 | enum DioErrorType { |
使用application/x-www-form-urlencoded编码
默认情况下, Dio 会将请求数据(除过String类型)序列化为 JSON
. 如果想要以 application/x-www-form-urlencoded
格式编码, 你可以显式设置contentType
:
1 | //Instance level |
这里有一个示例.
FormData
Dio支持发送 FormData, 请求数据将会以 multipart/form-data
方式编码, FormData中可以一个或多个包含文件 .
1 | FormData formData = new FormData.from({ |
注意: 只有 post 方法支持发送 FormData.
这里有一个完整的示例.
转换器
转换器Transformer
用于对请求数据和响应数据进行编解码处理。Dio实现了一个默认转换器DefaultTransformer
作为默认的 Transformer
. 如果你想对请求/响应数据进行自定义编解码处理,可以提供自定义转换器,通过 dio.transformer
设置。
请求转换器
Transformer.transformRequest(...)
只会被用于 ‘PUT’、 ‘POST’、 ‘PATCH’方法,因为只有这些方法才可以携带请求体(request body)。但是响应转换器Transformer.transformResponse()
会被用于所有请求方法的返回数据。
执行流
虽然在拦截器中也可以对数据进行预处理,但是转换器主要职责是对请求/响应数据进行编解码,之所以将转化器单独分离,一是为了和拦截器解耦,二是为了不修改原始请求数据(如果你在拦截器中修改请求数据(options.data),会覆盖原始请求数据,而在某些时候您可能需要原始请求数据). Dio的请求流是:
请求拦截器 >> 请求转换器 >> 发起请求 >> 响应转换器 >> 响应拦截器 >> 最终结果。
这是一个自定义转换器的示例.
设置Http代理
Dio 是使用 HttpClient发起的http请求,所以你可以通过配置 httpClient
来支持代理,示例如下:
1 | dio.onHttpClientCreate = (HttpClient client) { |
完整的示例请查看这里.
Https证书校验
有两种方法可以校验https证书,假设我们的后台服务使用的是自签名证书,证书格式是PEM格式,我们将证书的内容保存在本地字符串中,那么我们的校验逻辑如下:
1 | String PEM="XXXXX"; //证书内容 |
X509Certificate
是证书的标准格式,包含了证书除私钥外所有信息,读者可以自行查阅文档。另外,上面的示例没有校验host,是因为只要服务器返回的证书内容和本地的保存一致就已经能证明是我们的服务器了(而不是中间人),host验证通常是为了防止证书和域名不匹配。
对于自签名的证书,我们也可以将其添加到本地证书信任链中,这样证书验证时就会自动通过,而不会再走到badCertificateCallback
回调中:
1 | dio.onHttpClientCreate = (HttpClient client) { |
注意,通过setTrustedCertificates()
设置的证书格式必须为PEM或PKCS12,如果证书格式为PKCS12,则需将证书密码传入,这样则会在代码中暴露证书密码,所以客户端证书校验不建议使用PKCS12格式的证书。
请求取消
你可以通过 cancel token 来取消发起的请求:
1 | CancelToken token = new CancelToken(); |
注意: 同一个cancel token 可以用于多个请求,当一个cancel token取消时,所有使用该cancel token的请求都会被取消。
完整的示例请参考取消示例.
Cookie管理
你可以通过 cookieJar
来自动管理请求/响应cookie.
dio cookie 管理 API 是基于开源库 cookie_jar.
你可以创建一个CookieJar
或 PersistCookieJar
来帮您自动管理cookie, dio 默认使用 CookieJar
, 它会将cookie保存在内存中。 如果您想对cookie进行持久化, 请使用 PersistCookieJar
, 示例代码如下:
1 | var dio = new Dio(); |
PersistCookieJar
实现了RFC中标准的cookie策略. PersistCookieJar
会将cookie保存在文件中,所以 cookies 会一直存在除非显式调用 delete
删除.
更多关于 cookie_jar 请参考 : https://github.com/flutterchina/cookie_jar .
Copyright & License
此开源项目为Flutter中文网(https://flutterchina.club) 授权 ,license 是 MIT. 如果您喜欢,欢迎star.
Flutter中文网开源项目计划
开发一系列Flutter SDK之外常用(实用)的Package、插件,丰富Flutter第三方库,为Flutter生态贡献来自中国开发者的力量。所有项目将发布在 Github Flutter中文网 Organization ,所有源码贡献者将加入到我们的Organization,成为成员. 目前社区已有几个开源项目开始公测,欢迎您加入开发或测试,详情请查看: Flutter中文网开源项目。 如果您想加入到“开源项目计划”, 请发邮件到824783146@qq.com, 并附上自我介绍(个人基本信息+擅长/关注技术)。
Features and bugs
Please file feature requests and bugs at the issue tracker.