Flutter Http庫Dio 2.1正式釋出

wendux發表於2019-03-12

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的主要變化有:

  1. 支援Uri,在1.x中,Url只能是字串,2.1中所有API都提供了對應支援Uri的版本,如get方法有dio.get(...)dio.gerUri(...)

  2. 所有方法都支援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"], });
      複製程式碼
  3. 支援以Stream方式提交資料了;2.1中可以通過Stream的方式來提交二進位制資料了,詳細的示例可以參考這裡

  4. 支援以二進位制陣列形式接收資料了;1.x中如果要以二進位制形式接收響應資料則需要設定options.responseTypeResponseType.stream 來接收響應流,然後再通過讀取響應流來獲取完整的二進位制內容,而2.x中只需要設定為ResponseType.bytes,則可直接獲得響應流的而精緻陣列。

  5. API統一新增了onSendProgressonReceiveProgress 兩個回撥,用於監聽傳送資料和接收資料的具體精度,在1.x中只有在下載檔案和上傳formdata時才能監聽進度,而2.x中所有介面都可以了。

攔截器

  1. 支援設定多個攔截器;

    這樣我們就可以將一些功能單獨抽離,比如列印請求/響應日誌和cookie管理都可以單獨封裝在一個攔截器中,這樣在解耦的同時可以提高程式碼的可複用度。

    2.1中攔截器是一個佇列,攔截器將會按照FIFO順序執行,如果佇列中的某個攔截器返回了Response或Error,則請求結束,佇列後面的攔截器將不會再被執行。

  2. 預置了列印請求/響應日誌的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中新增了一些關於重定向資訊的欄位,有isRedirectredirectsrealUri

TransFormer

2.x中對於DefaultTransformer新增了一個jsonDecodeCallback,通過它可以定製json解碼器,這在flutter中非常有用,我們可以通過compute方法來在後臺進行json解碼,從而避免在UI執行緒對複雜json解碼時引起的介面卡頓,詳情請見這裡

HttpClientAdapter

HttpClientAdapter是 Dio 和 HttpClient之間的橋樑。2.0抽象出了adapter層,可以帶來兩個主要收益:

  1. 實現Dio於HttpClient的解耦,這樣可以方便的切換、定製底層網路庫。
  2. 可以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合併後的

另外,新增了一些新的配置項:

  1. cookies:可以新增一些公共cookie
  2. receiveDataWhenStatusError:當響應狀態碼不是成功狀態(如404)時,是否接收響應內容,如果是false,則response.data將會為null
  3. maxRedirects: 重定向最大次數。

相關文章