Dio 是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時、自定義適配器等。目前Dio在pub上綜合得分100分,排名已上榜pub首頁(All Tab下) !同時Dio也是Github上最受歡迎的Flutter第三方庫,項目地址:Dio-Github。
從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。
相比1.x,2.x在Restful API、攔截器、FormData等很多地方都進行了擴展和調整,除了這些,Dio在2.x中還引入Adapter層,為Mock接口數據和自定義底層網絡庫提供了支持。整體功能相比1.x有了很大的提升,因此我們強烈建議所有1.x用戶都能升級到2.1。
功能介紹
請參考: https://github.com/flutterchina/dio
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%5B%5D=1&selectedId%5B%5D=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解碼時引起的界面卡頓,詳情請見這里 。
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
: 重定向最大次數。