1. 程式人生 > >Android的HTTP客戶端選擇及HttpResponseCache的使用

Android的HTTP客戶端選擇及HttpResponseCache的使用

據Android Dalvik團隊的 同學講, 在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變得一樣強大和複雜了 ! \(^o^)/~

之前我們在軟體開發中,cache都是自己來寫,不管是圖片快取還是其他從網路獲取的資料,有了HttpResponseCache,它幫助我們可以很好的解決cache這個問題(我現在感覺他只適合cache一些小的資料,如果大量的圖片cache還是自己快取到SD卡上面去比較好)。

HttpResponseCache的好處:

1.明顯一點節約電,減少了網路請求。

2.開發者不用自己在去寫cache機制了。

3.最根本的一點就是,如果開發者在開發中不是使用的HttpClient, HttpDefaultClient..., 而是用 HttpURLConnection的話, 你根本不用改本來的 Code。

這個我們就不多說了,直接看示例:

在開發中你不用寫其他任何東西,只要在Application層將其啟動就好了 其他的全部交給HttpURLConnection處理就行。

  1. publicclass HttpCacheApplication extends Application {  
  2.     @Override
  3.     publicvoid onCreate() {  
  4.         super.onCreate();  
  5.         new Thread() {  
  6.             @Override
  7.             publicvoid run() {  
  8.                 enableHttpResponseCache();  
  9.             }  
  10.         }.start();  
  11.     }  
  12.     privatevoid enableHttpResponseCache() {  
  13.         try {  
  14.             long httpCacheSize = 10 * 1024 * 1024;// 10M
  15.             File httpCacheDir = new File(getCacheDir(), "http");  
  16.             Class.forName("android.net.http.HttpResponseCache")  
  17.                     .getMethod("install", File.classlong.class)  
  18.                     .invoke(null, httpCacheDir, httpCacheSize);  
  19.         } catch (Exception e) {  
  20.             Log.e("===>", e.getMessage(), e);  
  21.         }  
  22.     }  
  23. }  

接下來我們來看看HttpUrlConnection是怎麼處理的,怎麼快取的。
  1. publicclass MainActivity extends Activity {  
  2.     privatefinal String TAG = getClass().getSimpleName();  
  3.     ImageView img;  
  4.     Button msg;  
  5.     TextView tv;  
  6.     @Override
  7.     publicvoid onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.activity_main);  
  10.         img = (ImageView) findViewById(R.id.imageView1);  
  11.         tv = (TextView)findViewById(R.id.textView1);  
  12.         msg = (Button) findViewById(R.id.button1);  
  13.         msg.setOnClickListener(new OnClickListener() {  
  14.             @Override
  15.             publicvoid onClick(View v) {  
  16.                 new InternetTask().execute();  
  17.             }  
  18.         });  
  19.         findViewById(R.id.button2).setOnClickListener(new OnClickListener() {  
  20.             @Override
  21.             publicvoid onClick(View v) {  
  22.                 MainActivity.this.finish();  
  23.             }  
  24.         });  
  25.     }  
  26.     class InternetTask extends AsyncTask<String, String, Boolean> {  
  27.         Bitmap bitmap;  
  28.         String jsonStr;  
  29.         @Override
  30.         protectedvoid onPostExecute(Boolean result) {  
  31.             super.onPostExecute(result);  
  32.             img.setImageBitmap(bitmap);  
  33.             tv.setText(jsonStr);  
  34.         }  
  35.         @Override
  36.         protected Boolean doInBackground(String... params) {  
  37.             // Test download image
  38.             try {  
  39.                 URL url = new URL("http://news.baidu.com/resource/img/logo_news_137_46.png");  
  40.                 HttpURLConnection conn = (HttpURLConnection) (url  
  41.                         .openConnection());  
  42.                 conn.connect();  
  43.                 InputStream is = conn.getInputStream();  
  44.                 BitmapFactory.Options ops = new BitmapFactory.Options();  
  45.                 bitmap = BitmapFactory.decodeStream(is, null, ops);  
  46.                 is.close();  
  47.                 conn.disconnect();   
  48.             } catch (Exception e) {  
  49.                 Log.e(TAG, e.getMessage(), e);  
  50.             }  
  51.             // Test download JSON data
  52.             try {  
  53.                 URL url = new URL("http://www.baidu.com/");  
  54.                 HttpURLConnection conn = (HttpURLConnection) (url  
  55.                         .openConnection());  
  56.                 conn.connect();    
  57.                 BufferedReader reader = new BufferedReader(  
  58.                         new InputStreamReader(conn.getInputStream(), "UTF-8"));  
  59.                 jsonStr = reader.readLine();  
  60.                 InputStream is = conn.getInputStream();  
  61.                 is.close();  
  62.                 conn.disconnect();  
  63.             } catch (Exception e) {  
  64.                 Log.e(TAG, e.getMessage(), e);  
  65.             }  
  66.             returntrue;  
  67.         }  
  68.     }  
  69. }  
我們看下效果:

看下快取檔案,每個檔案會產生兩個檔案,一個是資料檔案,一個是http header 資訊


相關推薦

Android的HTTP客戶選擇HttpResponseCache的使用

據Android Dalvik團隊的 同學講, 在Android系統中可以使用兩種HTTP客戶端來收發HTTP資料. 一個就是大名鼎鼎的Apache HTTP Client, 而另外一個就是 HttpURLConnection. Apache HTTP Client

SVN客戶配置PHP程序員代碼導入

安裝完成 png color mys ef6 rip rto php程序 com 上一篇文章《部署社交網站(SVN+PHP+NGINX+MYSQL+MFS)》主要講了SVN群集部署,這篇文章以上篇為基礎繼續講解SVN客戶端的安裝和使用。首先在百度下載SVN客戶端並進行安裝(

zookeeper客戶操作JAVA程式碼操作CURD

總結:zookeeper相當於一個遠端平臺,我們可以將資料放在上面,他是一個樹形結構,每一個節點稱為一個Znode 資料模型:每個節點或稱為目錄,都可以存放資料並且存放節點,有雙重功能 重點watch機制: ZooKeeper 中,引入了 Watcher 機制來實現這種分散式的通知功能

Spring Boot2.0 Oauth2 伺服器和客戶配置原理

一、應用場景 為了理解OAuth的適用場合,讓我舉一個假設的例子。 有一個"雲沖印"的網站,可以將使用者儲存在Google的照片,沖印出來。使用者為了使用該服務,必須讓"雲沖印"讀取自己儲存在Google上的照片。 問題是隻有得到使用者的授權,Google才會同意"雲沖印"讀取這些

推薦一款好用的國外網盤 mega(附客戶下載使用教程)

國內,免費好用的網盤基本絕跡了。比如百度網盤,免費各種限速,速度坑的一比,雖然有一些方法可以突破百度網盤限速,不過百度網盤演算法也一直在更新,可能之前有用的方法後面就失效了。而 115 網盤,也是需要付費才能體驗比較好的服務,而且費用還不便宜。 現在介紹國外的一款網盤,名為 mega 網

IP-SAN客戶配置使用

做ISCSI發起程式我們分為一下幾個步驟 將網絡卡設定為靜態IP地址配置YUM軟體倉庫新增4塊硬碟建立RAID磁碟陣列和備份盤配置ISCSI服務端 在虛擬機器中新增4塊新硬碟,用於建立RAID 5磁碟陣列和備份盤 執行fdisk-l命令檢視一下硬碟是否新增

oracle客戶安裝PL/SQL安裝

1.安裝oracle客戶端後,設定oracle環境變數: 新增3個環境變數: 變數名:ORACLE_HOME      //客戶端安裝路徑 變數值:D:\Program Files\oracle      變數名:TNS

SVN客戶命令作用詳解

TortoiseSVN是windows下其中一個非常優秀的SVN客戶端工具。通過使用它,我們可以視覺化的管理我們的版本庫。不過由於它只是一個客戶端,所以它不能對版本庫

Mqtt for Java 客戶訂閱多執行緒UI展示

最近需要用mqtt做一個小程式,感測器釋出客戶端暫時不考慮,需要完成一個mqtt訂閱客戶端來實時接收感測器端發來的資訊,因為mqtt有現成的java第三方,所以選擇用java來完成,而在寫碼過程中發現訂閱資訊的回撥函式如果用單執行緒釋出這些資訊,會造成回撥函式阻塞,從而造成連

客戶選擇器的相關學習

  基本選擇器: 標籤(元素)選擇器    格式=====>標籤名{ 宣告的屬性} 類-----------選擇器           =====>這裡有個點(.)+類名稱{宣告的屬性} ID----

js獲取客戶IP地理位置

[php] view plain copy  print? 1.<?php      2.function get_ip_place(){      3.$ip=file_get_contents("http://fw.qq.com/ipaddress");      4.$ip=str

伺服器獲取客戶IP客戶IP變化

1.服務端獲取客戶端請求的IP等資訊request = javax.servlet.http.HttpServletRequest request.getRemoteAddr()獲取客戶端請求IP地址 request.getRemotePort() 獲取客戶端請求埠 req

獲取客戶IP所在位置

private string GetIPandAddr()     {         string sourceFileText = null;         Uri uri = new Uri("http://www.ikaka.com/ip/index.asp");         System.N

oracle11g客戶配置使用(Instant Client)

  Oracle官方給出的答案是:Instant Client。     首先,我們去此產品的首頁,選擇Windows32位版本     選擇資料庫對應版本:11.2(最新為V11.2.4.0)      前期準備:(任選一個)            

zabbix客戶安裝配置

win客戶端版本為:zabbix_agents_2.4.4.win linux客戶版本為:zabbix_agents_2.4.4.linux2_6.i386.tar.gz 一、linux客戶端安裝 1.新增zabbix使用者和組。 groupadd -

APP支付(支付寶和微信生成客戶簽名回撥驗籤)

<?php namespace Pn\Controller; use Think\Controller\RestController; class PayController extends RestController{ public function __

WebSocket 安卓客戶實現程式碼封裝

WebSocketDemo WebSocket 安卓客戶端的實現方式。 介紹 如果不想了解其中的原理可以直接拉到最後面的使用方式章節,按照教程使用即可,或者直接開啟 demo 檢視程式碼,程式碼地址:。 https://github.com/0x

VirtualBox5.2.16+Centos6.10下Zabbix3.2伺服器+Windows客戶安裝配置

基本根據官方文件的操作,選擇repository安裝 1 配置官方Zabbix源 sudo rpm -ivh http://repo.zabbix.com/zabbix/3.2/rhel/6/x86_64/zabbix-release-3.2-1.el6.noar

java用axis2生成webservice客戶程式碼使用方法

這兩天javaweb專案需要呼叫c#釋出的webService介面。自己琢磨了半天,到網上趙各種資料,有java自帶的wsimport方法,還有用axis2的jar包去生成。在實現中也遇到了一些問題,

java自帶wsimport命令生成webservice客戶程式碼服務呼叫

wsimport是jdk自帶的命令,可在jdk/bin目錄下找到wsimport.exe,根據wsdl文件生成客戶端中間程式碼,基於生成的程式碼編寫客戶端,可以省很多麻煩。 wsimport命令用法 wsimport [options] WSDL_UR