Dio 是一個強大的Dart Http請求庫,支援Restful API、FormData、攔截器、請求取消、Cookie管理、檔案上傳/下載、超時、自定義介面卡等。目前Dio在pub上綜合得分100分,排名已上榜pub首頁(All Tab下) !同時Dio也是Github上最受歡迎的Flutter第三方庫,專案地址:Dio-Github。
從1.0釋出至今,Dio受到了大量國內外開發者的關注,使用者遍佈世界各地。在受到開發者肯定的同時也收到了很多建議,為了讓Dio功能更強大、更易用,我們綜合了1.0中的各種反饋,在2.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。
Dio V2.1.x 變更列表
Restful API
2.x中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
:可以新增一些公共cookiereceiveDataWhenStatusError
:當響應狀態碼不是成功狀態(如404)時,是否接收響應內容,如果是false
,則response.data
將會為nullmaxRedirects
: 重定向最大次數。