關於Android的HTTP客戶端的小祕密

轉載自:http://blog.chengyunfeng.com/?p=196


據Android Dalvik團隊的Jesse Wilson 同學講, 在Android系統中可以使用兩種HTTP客戶端來收發HTTP數據.

一個就是大名鼎鼎的Apache HTTP Client, 而另外一個就是 HttpURLConnection.

Apache HTTP Client

DefaultHttpClient 和她的兄弟 AndroidHttpClient 是用於瀏覽器的及具擴展性的HTTP客戶端. 他們都有很多APIs. 他們的實現都很可靠並且只有很少的BUGs.

因爲已經有了一票APIs的存在, 所以Dalvik團隊的同學們想要改進這個客戶端並且不破壞其兼容性的情況下是非常非常困難滴! 並且Android團隊的同學們也並沒有負責Apache HTTP Client 的開發和維護!

HTTP URL Connection

而 HttpURLConnection 就不一樣了, 這傢伙是通用的 輕量級的一個HTTP客戶端實現,對於大多數App來說都是夠用的. 這傢伙功能簡潔並且很容易的增強其功能.

在 Froyo 發佈以前, HttpURLConnection 有一些非人讓人鬱悶的BUGs . 最鬱悶的是, 當你在可讀取的InputStream上調用 close()函數的時候會 污染連接池 (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這個版本中, Dalvik團隊的同學又添加了自動壓縮數據的功能. 當你調用HttpURLConnection的時候,她回自動的偷偷的添加gzip屬性到請求頭中,並且會自己解壓返回的數據, 開發者完全不用爲了處理壓縮數據而增加工作量, 只要服務器支持gzip就ok啦:

Accept-Encoding: gzip

如果你發現服務器返回的壓縮數據有問題,可以參考該類的doc文檔來看看如何禁用該功能!

由於Content-Length返回的是壓縮後的數據長度,所以使用 getContentLength() 函數得到的Buffer數據大小是不正確的哦! 你要使用從響應中一直讀取字節流直到InputStream.read()函數返回-1爲止.

在Gingerbread版本中,同樣也增強了HTTPs的功能. HttpsURLConnection嘗試和Server Name Indication (SNI)連接,這樣多個HTTPs主機可以共享同一個IP地址. 同樣支持壓縮和session tickets. 如果連接失敗,她會自動禁用這些功能去重新連接.

而在 Ice Cream Sandwich版本中,Dalvik團隊的同學又不安分了, 繼續添加了一些新的特性: 響應緩存(response cache) . 如果使用了緩存,那麼HTTP請求會有3種情況:

  • 完全緩存的結果將直接從本地緩存中返回,省去了聯網訪問服務器的過程, 在中國的龜速移動網絡環境中很有用哦
  • 有條件(期限)的緩存將通過服務器來判斷,客戶端將發送這樣一個請求”如果昨天得到的/foo.png這個圖片已經更新了的話,就返回給我一個新的圖片”,如果服務器更新了圖片就返回新的數據 如果沒有更新則返回”304 Not Modified ”.對於沒有更新的內容就節約了流量.
  • 對於沒有緩存過的內容就直接請求服務器的數據,然後把這個結果再放到緩存中去.
如果您想在Ice Cream Sandwich版本中使用緩存這個有用的功能,而又不想在其他版本的系統中導致程序Crash 該怎麼辦!
這個時候Java強大的反射就再一次的挽救廣大的開發者於水火之中! 代碼如下:
    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) {
        }
    }
如果有”android.net.http.HttpResponseCache“這個類 就使用緩存,沒有就當沒這回事, 該怎麼滴就怎麼滴了.
注意: 如果你想使用緩存, 還有配置你的服務器讓她也支持緩存哦!

開發者該選擇哪個客戶端使用呢?

在Eclair 和 Froyo版本中, Apache HTTP Client具有更少的BUGs,所以應該在這個版本中用Apache.
而對於Gingerbread 及其以後的版本中, HttpURLConnection 是最好的選擇. 其簡潔的API和輕量級的實現用於Android系統再適合不過了. 對開發者透明的壓縮和緩存實現,可以減少網絡數據傳輸量, 提高程序響應速度 同時也節約設備電源.
新的App應該使用 HttpURLConnection;Dalvik團隊的同學將會把他們的無聊時間繼續投入到這個實現上來,從而增強其功能.
或許 到未來的某一天你發現HttpURLConnection和Apache HTTP Client變得一樣強大和複雜了 ! 


Read more: http://blog.chengyunfeng.com/?p=196#ixzz2c70lCixJ
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章