Android’s HTTP Clients--Android HTTP 客戶端選擇

大多數網絡相關的Android應用都會使用HTTP來接收和發送數據。Android中有2種HTTP客戶端:HttpURLConnection 和Apache HTTP Client. 它們都支持HTTPS,文件流上傳和下載,IPv6,并可以配置超時和連接池。

Apache HTTP Client

DefaultHttpClient和與它類似(sibling)的AndroidHttpClient 都是可拓展的支持web瀏覽器的HTTP客戶端.它們都有著繁多而復雜的API,實現都很穩定,很少有Bug.

但是大量繁雜的API使得想不打破兼容性去改進它們變得非常困難.所以Android Team 不再維護(actively working)Apache HTTP Client.

But the large size of this API makes it difficult for us to improve it without breaking compatibility. The Android team is not actively working on Apache HTTP Client.

HttpURLConnection

HttpURLConnection是一個多用途的(general-purpose)、輕量級的HTTP客戶端,適用于大多數的應用。這個類有點簡陋(humble beginnings),但是它的 focused API使得我們可以穩定的進行改進.

HttpURLConnection is a general-purpose, lightweight HTTP client suitable for most applications. This class has humble beginnings, but its focused API has made it easy for us to improve steadily.

在Android Froyo之前,HttpURLConnection 有很多令人詛喪的bug.尤其是,在一個可讀的InputStream上調用close()會摧毀連接池(poison the connection pool). 可以通過關閉連接池來解決:

    private void disableConnectionReuseIfNecessary() {
       // HTTP connection reuse which was buggy pre-froyo
       if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
              System.setProperty("http.keepAlive", "false");
          }
    }

在Gingerbread中,我們添加了傳輸層的response壓縮(comprression). HttpURLConnection會自動把這個頭消息(header)添加到返回的request里,并處理對應的回復:

 Accept-Encoding: gzip

應該充分利用這一點,可以通過配置你的web服務器來為客戶端壓縮response來支持它.
如果response壓縮存在問題,這個類的文檔 會告訴你如何關閉它.

自從HTTP的內容長度頭返回了壓縮的大小,使用 getContentLength() 來為未壓縮的數據計算buffers的長度。相反的,從 response里讀取bytes直到InputStream.read()返回-1.在GingerBread中我們在HTTPS上也作出了一些改進。 HttpsURLConnection在連接時會嘗試使用Server Name Indication(SNI),這個允許多個HTTPS 主機共享一個IP地址,它也支持壓縮和Session標簽(Session tickets).當連接失敗時,它會自動重試 without these features.這使得HttpsURLConnection在連接最新的(up-to-date)服務器時更有效,而不用破壞與舊服務器的兼容性.

Since HTTP’s Content-Length header returns the compressed size, it is an error to use [getContentLength()] to size buffers for the uncompressed data. Instead, read bytes from the response until [InputStream.read()] returns -1.We also made several improvements to HTTPS in Gingerbread. [HttpsURLConnection] attempts to connect with Server Name Indication which allows multiple HTTPS hosts to share an IP address. It also enables compression and session tickets. Should the connection fail, it is automatically retried without these features. This makes HttpsURLConnection efficient when connecting to up-to-date servers, without breaking compatibility with older ones.

在Ice Cream Sandwich中,我們添加了一個response緩存.使用這個緩存,HTTP 請求可以滿足使用下面三種方式中的一種:
所有緩存的回復都會從 本地存儲器中直接讀取并提供出來。因為無網絡連接需要這種回復立即可見。

有條件的緩存的回復應該有web服務器的freshness驗證.客戶端會發送一個request,比如 “Give me /foo.png if it changed since yesterday” .服務器會進行response,或回復一個最新的內容(內容發生更改),后返回一個304 Not Modified消息(內容未更改).

未緩存的response則是由服務器提供.這些回復會被存儲起來已備后面使用.

Uncached responses are served from the web. These responses will get stored in the response cache for later.

In Ice Cream Sandwich, we are adding a response cache. With the cache installed, HTTP requests will be satisfied in one of three ways:
Fully cached responses are served directly from local storage. Because no network connection needs to be made such responses are available immediately.

Conditionally cached responses must have their freshness validated by the webserver. The client sends a request like “Give me /foo.png if it changed since yesterday” and the server replies with either the updated content or a 304 Not Modified
status. If the content is unchanged it will not be downloaded!

使用反射來開啟設備上的HTTP response緩存來支持這個特性.下面的示例會打開 Ice Cream Sandwich版本上的response緩存而不會影響更早的版本.

     private void enableHttpResponseCache() {   
           try {     
                long httpCacheSize = 10 * 1024 * 1024; // 10 MiB      
                File httpCacheDir = new File(getCacheDir(), "http");                 
                Class.forName("android.net.http.HttpResponseCache") .getMethod("install", File.class, long.class).invoke(null, httpCacheDir, httpCacheSize);    
             } catch (Exception httpResponseCacheNotAvailable) 
             {   }}

Use reflection to enable HTTP response caching on devices that support it. This sample code will turn on the response cache on Ice Cream Sandwich without affecting earlier releases:

你也可以通過配置你的web服務器來在你的HTTP回復中設置緩存頭。
You should also configure your Web server to set cache headers on its HTTP responses.

哪一個客戶端是最佳的呢?

Apache HTTP client在Eclair 和 Froyo中有著更少的bug.在這些發行版中這是最好的選擇.

對于Gingerbread 和之后的版本, HttpURLConnection 是最佳的選擇.它簡潔的API和小的體積使它更能適合Android.傳輸壓縮和response緩存減少了網絡使用,提高了速度并且更加省電。新的應用應該使用 HttpURLConnection,這也是我們以后發力的方向。

For Gingerbread and better, HttpURLConnection is the best choice. Its simple API and small size makes it great fit for Android. Transparent compression and response caching reduce network use, improve speed and save battery. New applications should use HttpURLConnection; it is where we will be spending our energy going forward.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,993評論 19 139
  • 原文https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html...
    梁行之閱讀 1,175評論 0 0
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,593評論 25 708
  • 我能想到最好的時光,便是老光陰, 我能記住最美的剎那,也是那些泛著舊色的陳年記憶! 獨自逛小街,轉轉舊書攤,拿起一...
    時光散落在人間閱讀 335評論 4 5
  • 1、Butterknife是什么? Butterknife是一個依托Java的注解機制來實現輔助代碼生成的框架 2...
    DevWang閱讀 1,694評論 0 52