大多數(shù)Android應(yīng)用都需要連接網(wǎng)絡(luò),使用HTTP來發(fā)送和接收數(shù)據(jù)溃睹。Android包含兩種HTTP客戶端:HttpURLConnection和Apache HTTP Client褥琐。它們都支持HTTPS状飞,流的上傳和下載商玫,超時(shí)配置疹娶,IPv6和連接池伴栓。
Apache HTTP客戶端
DefaultHttpClient和AndroidHttpClient都是適用于web瀏覽器的可擴(kuò)展HTTP客戶端。它們有大量的雨饺、靈活的API钳垮。它們的實(shí)現(xiàn)穩(wěn)定惜姐,幾乎沒有bug榕订。
但是大數(shù)量的API使得我們很難在不破壞兼容性的情況下對(duì)其改善,同時(shí)Google的Android團(tuán)隊(duì)沒有積極致力于Apache HTTP客戶端沈矿。
HttpURLConnection
HttpURLConnection是一個(gè)通用的移斩、輕量的肚医、適用于大多數(shù)應(yīng)用的HTTP客戶端绢馍。它的API量少,但主要的API使得我們可以穩(wěn)固地進(jìn)行改善肠套。
在Froyo之前舰涌,HttpURLConnection有一些令人沮喪的bug。尤其在一個(gè)可讀輸入流時(shí)調(diào)用close()會(huì)污染連接池你稚。通過禁用連接池來解決這個(gè)問題:
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瓷耙,添加了透明響應(yīng)壓縮。HttpURLConnection會(huì)自動(dòng)添加下面的header到發(fā)出的請(qǐng)求中入宦,并且處理相應(yīng)的響應(yīng):
Accept-Encoding: gzipf
使用這個(gè)需要配置Web服務(wù)器來對(duì)客戶端進(jìn)行壓縮響應(yīng)哺徊。
由于HTTP的Content-Length頭返回壓縮的大小,因此使用getContentLength()來給未壓縮數(shù)據(jù)定義緩存大小是錯(cuò)誤的乾闰,而應(yīng)該從響應(yīng)中讀取字節(jié)直到InputStream.read()返回-1落追。
在Gingerbread中做了些關(guān)于HTTPS的提升。HttpsURLConnection嘗試連接Server Name Indication(SNI:允許多個(gè)HTTPS hosts共享一個(gè)IP地址)涯肩。它同時(shí)啟用了壓縮和會(huì)話許可證轿钠。如果連接失敗,它會(huì)自動(dòng)不用這些特性嘗試病苗。這樣使得當(dāng)連接最新的服務(wù)器時(shí)HttpsURLConnection有效率疗垛,而不會(huì)破壞之前的兼容性。
在Ice Cream Sandwich硫朦,添加了一個(gè)響應(yīng)緩存贷腕。當(dāng)緩存建立了,HTTP請(qǐng)求將會(huì)是以下三種方式中的一種:
- 所有緩存響應(yīng)將會(huì)直接從本地存儲(chǔ)獲取服務(wù)咬展。因?yàn)闆]有網(wǎng)絡(luò)連接需要建立泽裳,響應(yīng)可以立即可用。
- 有條件地緩存響應(yīng)必須通過webserver有它們的刷新有效期破婆′套埽客戶端發(fā)送一個(gè)請(qǐng)求“Give me /foo.png if it changed since yesterday”,然后服務(wù)器用更新后的內(nèi)容或者一個(gè)304 Not Modified狀態(tài)回復(fù)祷舀。如果內(nèi)容沒有改變將不會(huì)進(jìn)行下載瀑梗。
- 未緩存響應(yīng)將會(huì)從網(wǎng)絡(luò)獲取服務(wù)。這些響應(yīng)將會(huì)在之后存儲(chǔ)在響應(yīng)緩存中裳扯。
使用反射來在支持的設(shè)備上啟用HTTP響應(yīng)緩存抛丽。下面是示例代碼來在Ice Cream Sandwich上打開響應(yīng)緩存而不影響之前的版本:
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) {
}
}
也應(yīng)該配置Web Server來在HTTP響應(yīng)上設(shè)置緩存頭。
哪個(gè)客戶端是最好的饰豺?
Apache HTTP客戶端在Eclair和Froyo上幾乎沒有bug亿鲜,它是這些版本的最好選擇。
對(duì)于Gingerbread和之后的版本哟忍,HttpURLConnection是最好的選擇狡门,它簡(jiǎn)單的API和小體積使得很適合Android。透明壓縮和響應(yīng)緩存減少了網(wǎng)絡(luò)流量锅很,提升了速度其馏,節(jié)省了電池。
原文鏈接:
http://android-developers.blogspot.com/2011/09/androids-http-clients.html
Http客戶端的相關(guān)故事
- android-async-http內(nèi)部實(shí)現(xiàn)基于HttpClient爆安。
- Volley在Gingerbread及之上使用HttpURLConnection叛复,其他情況使用的HttpClient。
- Google在Android 6.0版本刪除了HttpClient相關(guān)API扔仓。