Android 網絡請求框架對比分析

一、網絡框架的基本結構

在分析其它框架之前,先做一個簡易的網絡請求框架。這裏的結構和 Volley 一致,主要分爲 4 部分,如圖:

simple_net_framework

  • 第一部分:各種請求類型,如 JsonRequest、StringRequest 等。
  • 第二部分:消息隊列,消息隊列維護了提交給網絡框架的請求列表,並且根據相應的規則進行排序。
  • 第三部分:Executor,也就是網絡的執行者。該 Executor 繼承自 Thread,在 run 方法中循環訪問第二部分的請求隊列,請求完成之後將結果投遞給UI線程。
  • 第四部分:Response投遞類,在第三部分的 Executor 中執行網絡請求,Executor 是 Thread,但是我們並不能在主線程中更新UI,因此我們使用 ResponseDelivery 來封裝 Response 的投遞,保證Response執行在UI線程。

二、幾個高 star 框架特徵

1,okhttp
  • OkHttp 是一個高效的 HTTP 庫,它實現了幾乎和java.net.HttpURLConnection一樣的API:

    • Http2.0 的支持,共享同一個Socket來處理同一個服務器的所有請求
    • 如果 Http2.0 不可用,通過連接池來減少請求延遲
    • 支持傳輸 GZIP 來減少數據流量
    • 緩存 Response,避免相同的請求
  • 框架圖:

    okhttp_construct

  • 主要是通過 Diapatcher 不斷從RequestQueue中取出請求(Call),根據是否已緩存調用 CacheNetwork 這兩類數據獲取接口之一,從內存緩存或是服務器取得請求的數據。該引擎有同步和異步請求,同步請求通過 Call.execute() 直接返 回當前的 Response ,而異步請求會把當前的請求Call.enqueue添加(AsyncCall)到請求隊列中,並通過回調(Callback) 的方式來獲取最後結果。

2,retrofit

Retrofit 是一個類型安全的 REST 客戶端,在 Retrofit2 依賴了 OkHttp。在使用上擁有如下優點:

  1. 可以利用接口,方法和註解參數(parameter annotations)來聲明式定義一個請求應該如何被創建。
  2. 支持序列化機制(JSON/XML 協議)
  3. 在一個類型中的同步和異步請求

Retrofit2 發佈會鏈接:https://realm.io/cn/news/droidcon-jake-wharton-simple-http-retrofit-2

3,volley

Volley 是 Google 在 2013 年推出的 Android 異步網絡請求框架和圖片加載框架。

  • Volley 的主要特點:

    • 擴展性強。Volley 中大多是基於接口的設計,可配置性強。
    • 一定程度符合 Http 規範,包括返回 ResponseCode(2xx、3xx、4xx、5xx)的處理,請求頭的處理,緩存機制的支持等。並支持重試及優先級定義。
    • 默認 Android2.3 及以上基於 HttpURLConnection,2.3 以下基於 HttpClient 實現,這兩者的區別及優劣在4.2.1 Volley中具體介紹。
    • 提供簡便的圖片加載工具。
  • 總體設計圖

    volley_construction

  • 通過兩種Dispatch Thread不斷從RequestQueue中取出請求,根據是否已緩存調用Cache或Network這兩類數據獲取接口之一,從內存緩存或是服務器取得請求的數據,然後交由ResponseDelivery去做結果分發及回調處理。

三、Android 的幾種網絡連接方式

Apache HttpClient 已不被推薦使用,並在 6.0 上被刪除。Google 推薦在 Android 上使用 HttpUrlConnection。DefaultHttpClient和它的兄弟AndroidHttpClient都是HttpClient具體的實現類,它們都擁有衆多的API,而且實現比較穩定,bug數量也很少。但同時也由於HttpClient的API數量過多,使得我們很難在不破壞兼容性的情況下對它進行升級和擴展。雖然高效穩定,但是維護成本高昂,故android 開發團隊不願意在維護該庫而是轉投更爲輕便的 HttpUrlConnection。

HttpURLConnection 是一種多用途、輕量極的 HTTP 客戶端,使用它來進行 HTTP 操作可以適用於大多數的應用程序。雖然 HttpURLConnection 的 API 提供的比較簡單,但是同時這也使得我們可以更加容易地去使用和擴展它。在 Android 2.2 版本之前,HttpURLConnection 一直存在着一些令人厭煩的 BUG,因此 Volley 框架在 2.2 之前使用的是 HttpClient。

OKHttp 是一款高效的 HTTP 客戶端,支持 SPDY(或HTTP)、連接池、GZIP 和 HTTP 緩存,使用 Okio 來大大簡化數據的訪問與存儲。同時處理了很多網絡疑難雜症,會從很多常用的連接問題中自動恢復,處理了代理服務器問題和SSL握手失敗問題。Android4.4 開始 HttpURLConnection 的底層實現採用的是 OkHttp。

四、Retrofit 的基本使用

官方文檔:http://square.github.io/retrofit/

從 GitHub 的 star 排名來看,Retrofit 數量是最多的,其次是 Okhttp,並且 Retrofit 的網絡請求框架也是依賴 OKhttp 的,在網絡性能上相當不錯;又因爲 Retrofit 通過接口註解的方式定義 Http Api,可以很方便的管理和調用;另外 GitHub 上還有一些基於 Okhttp 框架拓展的新框架(如 OkGo),使該框架也具有較強的拓展性。最終決定採用 Retrofit 作爲現階段我們應用網絡請求的主流框架。

1,基本配置

請求的 Http 接口需要定義在 Java 接口中,如下:

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

用 Retrofit 創建一個實現了 GitHubService 接口的對象:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

最後調用接口中的方法來請求服務器,並返回一個 Call 對象:

Call<List<Repo>> repos = service.listRepos("octocat");
2,Get 請求

@Path
在替換 Http 接口中的路徑時,用 @path 屬性。如下:

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);

@Query
在替換 Http 接口中的參數時,用 @Query 屬性。如下:

@GET("group/123456/users")
Call<List<User>> groupList(@Query("sort") String sort);

等同於: group/123456/users?sort=name

@QueryMap
在請求參數過多時,可以通過鍵值對的形式,如下:

@GET("group/123456/users")
Call<List<User>> groupList(@QueryMap Map<String, String> options);
3,Post 請求

@Body
可以把一個對象作爲請求內容傳遞,用法如下:

@POST("users/new")
Call<User> createUser(@Body User user);

@Field
在方法的參數中添加 @Field 註解,並在方法上加上 @FormUrlEncoded 註解,代碼如下:

@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);

@Part
多部分請求在方法上添加 @Multipart,並在參數前加入 @Part 屬性,代碼如下:

@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
4,請求頭修改

@Headers
請求頭信息通過 @Headers 註釋設置,代碼如下:

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();

// 多條參數
@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);

另外,可以通過註解動態的使用,如下:

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

原文鏈接:http://www.ionesmile.com/android/network-framework

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章