Android訪問網(wǎng)絡,使用HttpURLConnection還是HttpClient?
本文屬于收藏轉載,侵刪。
最近在研究Volley框架的源碼,發(fā)現(xiàn)它在HTTP請求的使用上比較有意思,在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。我也比較好奇這么使用的原因,于是專門找到了一位Google的工程師寫的一篇博客,文中對HttpURLConnection和HttpClient進行了對比,下面我就給大家簡要地翻譯一下。
大多數(shù)的Android應用程序都會使用HTTP協(xié)議來發(fā)送和接收網(wǎng)絡數(shù)據(jù),而Android中主要提供了兩種方式來進行HTTP操作,HttpURLConnection和HttpClient。這兩種方式都支持HTTPS協(xié)議、以流的形式進行上傳和下載、配置超時時間、IPv6、以及連接池等功能。
HttpClient
DefaultHttpClient和它的兄弟AndroidHttpClient都是HttpClient具體的實現(xiàn)類,它們都擁有眾多的API,而且實現(xiàn)比較穩(wěn)定,bug數(shù)量也很少。
但同時也由于HttpClient的API數(shù)量過多,使得我們很難在不破壞兼容性的情況下對它進行升級和擴展,所以目前Android團隊在提升和優(yōu)化HttpClient方面的工作態(tài)度并不積極。
HttpURLConnection
HttpURLConnection是一種多用途、輕量極的HTTP客戶端,使用它來進行HTTP操作可以適用于大多數(shù)的應用程序。雖然HttpURLConnection的API提供的比較簡單,但是同時這也使得我們可以更加容易地去使用和擴展它。
不過在Android 2.2版本之前,HttpURLConnection一直存在著一些令人厭煩的bug。比如說對一個可讀的InputStream調用close()方法時,就有可能會導致連接池失效了。那么我們通常的解決辦法就是直接禁用掉連接池的功能:
[java]?view plain?copy ?private?void?disableConnectionReuseIfNecessary()?{?? ????//?這是一個2.2版本之前的bug?? ????if?(Integer.parseInt(Build.VERSION.SDK)?<?Build.VERSION_CODES.FROYO)?{?? ????????System.setProperty("http.keepAlive",?"false");?? ????}?? }?? 在Android 2.3版本的時候,我們加入了更加透明化的響應壓縮。HttpURLConnection會自動在每個發(fā)出的請求中加入如下消息頭,并處理相應的返回結果:
Accept-Encoding: gzip
配置你的Web服務器來支持對客戶端的響應進行壓縮的功能,從而可以在這一改進上獲取到最大的好處。如果在壓縮響應的時候出現(xiàn)了問題,這篇文檔會告訴你如何禁用掉這個功能。
但是如果啟動了響應壓縮的功能,HTTP響應頭里的Content-Length就會代表著壓縮后的長度,這時再使用getContentLength()方法來取出解壓后的數(shù)據(jù)就是錯誤的了。正確的做法應該是一直調用InputStream.read()方法來讀取響應數(shù)據(jù),一直到出現(xiàn)-1為止。
我們在Android 2.3版本中還增加了一些HTTPS方面的改進,現(xiàn)在HttpsURLConnection會使用SNI(Server Name Indication)的方式進行連接,使得多個HTTPS主機可以共享同一個IP地址。除此之外,還增加了一些壓縮和會話的機制。如果連接失敗,它會自動去嘗試重新進行連接。這使得HttpsURLConnection可以在不破壞老版本兼容性的前提下,更加高效地連接最新的服務器。
在Android 4.0版本中,我們又添加了一些響應的緩存機制。當緩存被安裝后(調用HttpResponseCache的install()方法),所有的HTTP請求都會滿足以下三種情況:
所有的緩存響應都由本地存儲來提供。因為沒有必要去發(fā)起任務的網(wǎng)絡連接請求,所有的響應都可以立刻獲取到。
視情況而定的緩存響應必須要有服務器來進行更新檢查。比如說客戶端發(fā)起了一條類似于 “如果/foo.png這張圖片發(fā)生了改變,就將它發(fā)送給我” 這樣的請求,服務器需要將更新后的數(shù)據(jù)進行返回,或者返回一個304 Not Modified狀態(tài)。如果請求的內容沒有發(fā)生,客戶端就不會下載任何數(shù)據(jù)。
沒有緩存的響應都是由服務器直接提供的。這部分響應會在稍后存儲到響應緩存中。
由于這個功能是在4.0之后的版本才有的,通常我們就可以使用反射的方式來啟動響應緩存功能。下面的示例代碼展示了如何在Android 4.0及以后的版本中去啟用響應緩存的功能,同時還不會影響到之前的版本:
[java]?view plain?copy ?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)?{?? ????}?? }?? 你也應該同時配置一下你的Web服務器,在HTTP響應上加入緩存的消息頭。
哪一種才是最好的?
在Android 2.2版本之前,HttpClient擁有較少的bug,因此使用它是最好的選擇。
而在Android 2.3版本及以后,HttpURLConnection則是最佳的選擇。它的API簡單,體積較小,因而非常適用于Android項目。壓縮和緩存機制可以有效地減少網(wǎng)絡訪問的流量,在提升速度和省電方面也起到了較大的作用。對于新的應用程序應該更加偏向于使用HttpURLConnection,因為在以后的工作當中我們也會將更多的時間放在優(yōu)化HttpURLConnection上面。