bitmapfun項目 看到一個函數[在使用HttpURLConnection下載之前調用]:
/**
* Workaround for bug pre-Froyo, see here for more info:
* http://android-developers.blogspot.com/2011/09/androids-http-clients.html
*/
public static void disableConnectionReuseIfNecessary() {
// HTTP connection reuse which was buggy pre-froyo
if (hasHttpConnectionBug()) {
System.setProperty("http.keepAlive", "false");
}
}
/**
* Check if OS version has a http URLConnection bug. See here for more information:
* http://android-developers.blogspot.com/2011/09/androids-http-clients.html
*
* @return
*/
public static boolean hasHttpConnectionBug() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO;
}
說是android 2.2之前HttpURLConnection 存在的bug,, 當你在可讀取的InputStream上調用 close()函數的時候會 污染連接池 (connection pool). 可以通過禁用連接池的方法還解決這個問題。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
大多數需要網絡連接的Android應用都會使用HTTP來傳輸數據。Android自帶了兩個HTTP客戶端:HttpURLConnection和Apache HTTP Clinent。它們都支持HTTPS,文件上傳下載,配置超時,IPV6及連接池。
Apache HTTP Client
DefaultHttpClient 及其相似的 AndroidHttpClient 都是HttpClient的擴展適用於Web瀏覽器。它們有豐富的可擴展的API,同時也很穩定沒有什麼Bug。但是這裏重量級的API讓我們難以修改後保證它的兼容性,因爲Android團隊並沒有負責Apache
HTTP Client 的開發和維護!
HttpURLConnection
HttpURLConnection是一個通用的,輕量級的適用於絕大多數應用的HTTP客戶端。這個類比較底層,但我們可以很容易的穩步修改它的關鍵的API。
在Froyo(2.2)之前,HttpURLConnection有幾個煩人的Bug,特別是,在一個可讀的InputStream中調用close()會
污染連接池,一個解決方案就是在低android版本中禁用連接池。
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(2.3)這個版本中, Dalvik團隊又添加了自動壓縮數據的功能. 當你調用HttpURLConnection的時候,它會自動的添加gzip屬性到請求頭中,並且會自己解壓返回的數據, 開發者完全不用爲了處理壓縮數據而增加工作量, 只要服務器配置支持gzip就行了:
Accept-Encoding: gzip
如果你發現服務器返回的壓縮數據有問題,可以參考HttpURLConnection的文檔來禁用該功能!
因爲HTTP客戶端的Content-Length頭部返回的是壓縮後的大小,所以使用getContentLength()來獲得解壓後的數據塊的大小是錯誤的。你應該從響應中讀取字節直到InputStream.read()返回-1。
同時我們對在Gingerbread中的HTTPS連接做了一些優化,當HttpsURLConnection嘗試連接SNI(Server Name Indication)將允許多個hosts共享一個IP地址。同樣支持壓縮和Session tickets。如果連接失敗,將自動重試(it is automatically retried without these features)。這使得HttpURLConnection在連接新的服務器時更有效,同時不破壞向下兼容。
在Ice Cream Sandwich(4.X)中,我們添加了響應緩存。有了緩存,HTTP請求就會滿足下面三種方式:
(1)完全緩存的響應將直接從本地存在中獲得。因爲無需進行網絡連接 ,這樣的響應可以馬上獲得。
(2)條件緩存的響應必須到服務器驗證是否過期,客戶端發送一個請求如"給我 /foo.png 如果從昨天后發生了改變的話",然後服務器響應返回更新的內容 或者一個304 Not Modified狀態。如果內容沒有更新,則將不會下載 。
(3)非緩存的響應將從web端獲得,這些請求會存儲在響應緩存中以務後用。
可以利用反射來在支持的設備中開啓HTTP 響應緩存 。下面的代碼將在4.0之後的版本的開啓響應緩存 。而不會影響之前的版本。
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) {
}
}
同時你需要配置你的服務器來在HTTP響應中設置緩存頭部。
哪一個客戶端最好?
在Eclair(2.1)和Froyo(2.2)中,Apache HTTP Client(相比HttpURLConnection)沒有什麼Bug,
對於這些發行版,它是最好的選擇。
對於 Gingerbread(2.3)及之後的版本。HttpURLConnection是最好的選擇。它的簡單輕量最適合android。
壓縮,緩存響應以減少網絡連接,提升速度,省電,新的應用應該使用HttpURLConnection,它也是我們將來的着力點。