Android有兩套http的API,剛開始使用網絡編程時多少有些迷惑到底用哪一個好呢?其實孰優孰劣無需再爭論,google已經指出HttpUrlConnection是Android更優的選擇,並在SDK文檔中引用了博客(須要代理訪問)http://android-developers.blogspot.com/2011/09/androids-http-clients.html來闡述各自的優缺點。國內也有些博客大體翻譯了上面的內容,並對了一些測試,惋惜測試不嚴密,某博客甚至得出HttpUrlConnection的下載速度快幾倍的結論,其實並無公平反映出兩者的下載速度。html
雖然我已經使用過HttpUrlConnection實現了一個輕量級http引擎用於下載,可是好奇心仍是促使我寫了一個測試程序用於比較兩者的性能。因爲HttpClient僅僅是一個接口,因此我選用了其實現類DefaultHttpClient和HttpUrlConnection作比較,方法很簡單,分別下載同一個文件10次,而後計算耗時的平均值,測試代碼片斷以下:android
1 2 @Override 3 public void onClick(View v) 4 { 5 if (v.equals(mTestHttpClientBtn)) 6 { 7 new Thread(new Runnable() 8 { 9 @Override 10 public void run() 11 { 12 long averageTime = 0; 13 for (int i = 0; i < 10; i++) 14 { 15 File file = new File(getFilesDir(), String.valueOf(i) + ".file"); 16 FileOutputStream fileOutputStream = null; 17 try 18 { 19 fileOutputStream = new FileOutputStream(file); 20 } 21 catch (FileNotFoundException e) 22 { 23 Log.e(TAG, "", e); 24 return; 25 } 26 27 long startTime = System.currentTimeMillis(); 28 testHttpClient(fileOutputStream); 29 long stopTime = System.currentTimeMillis(); 30 31 averageTime += stopTime - startTime; 32 } 33 averageTime /= 10; 34 35 // 測試完成 36 Message msg = new Message(); 37 msg.what = MSG_TEST_HTTP_CLIENT_DONE; 38 msg.obj = averageTime; 39 mHandler.sendMessage(msg); 40 } 41 }).start(); 42 43 return; 44 } 45 46 if (v.equals(mTestHttpUrlConnectionBtn)) 47 { 48 new Thread(new Runnable() 49 { 50 @Override 51 public void run() 52 { 53 long averageTime = 0; 54 for (int i = 0; i < 10; i++) 55 { 56 File file = new File(getFilesDir(), String.valueOf(i + 10) + ".file"); 57 FileOutputStream fileOutputStream = null; 58 try 59 { 60 fileOutputStream = new FileOutputStream(file); 61 } 62 catch (FileNotFoundException e) 63 { 64 Log.e(TAG, "", e); 65 return; 66 } 67 68 long startTime = System.currentTimeMillis(); 69 testHttpUrlConnection(fileOutputStream); 70 long stopTime = System.currentTimeMillis(); 71 72 averageTime += stopTime - startTime; 73 } 74 averageTime /= 10; 75 76 // 測試完成 77 Message msg = new Message(); 78 msg.what = MSG_TEST_HTTP_URL_CONNECTION_DONE; 79 msg.obj = averageTime; 80 mHandler.sendMessage(msg); 81 } 82 }).start(); 83 84 return; 85 } 86 } 87 88 private void testHttpClient(FileOutputStream fileOutputStream) 89 { 90 DefaultHttpClient httpClient = new DefaultHttpClient(); 91 92 HttpEntity entity = null; 93 InputStream inputStream = null; 94 try 95 { 96 HttpGet httpGet = new HttpGet(TEST_URL); 97 HttpResponse httpResponse = httpClient.execute(httpGet); 98 99 StatusLine statusLine = httpResponse.getStatusLine(); 100 if (statusLine == null) 101 { 102 throw new Exception("no status line !!!"); 103 } 104 int responseCode = statusLine.getStatusCode(); 105 if (responseCode < 200 || responseCode >= 300) 106 { 107 throw new Exception("response error !!!"); 108 } 109 entity = httpResponse.getEntity(); 110 if (entity == null) 111 { 112 throw new Exception("no entity !!!"); 113 } 114 inputStream = entity.getContent(); 115 int bytesRead = -1; 116 byte[] buffer = new byte[4096]; 117 while ((bytesRead = inputStream.read(buffer)) != -1) 118 { 119 fileOutputStream.write(buffer, 0, bytesRead); 120 } 121 } 122 catch (Exception e) 123 { 124 Log.e(TAG, "", e); 125 } 126 finally 127 { 128 try 129 { 130 if (inputStream != null) 131 { 132 inputStream.close(); 133 } 134 135 if (entity != null) 136 { 137 entity.consumeContent(); 138 } 139 140 if (fileOutputStream != null) 141 { 142 fileOutputStream.flush(); 143 fileOutputStream.close(); 144 } 145 } 146 catch (Exception e) 147 { 148 Log.e(TAG, "", e); 149 } 150 } 151 } 152 153 private void testHttpUrlConnection(FileOutputStream fileOutputStream) 154 { 155 HttpURLConnection httpURLConnection = null; 156 InputStream inputStream = null; 157 try 158 { 159 httpURLConnection = (HttpURLConnection) new URL(TEST_URL).openConnection(); 160 httpURLConnection.setRequestMethod("GET"); 161 httpURLConnection.connect(); 162 163 int responseCode = httpURLConnection.getResponseCode(); 164 if (responseCode < 200 || responseCode >= 300) 165 { 166 throw new Exception("response error !!!"); 167 } 168 inputStream = httpURLConnection.getInputStream(); 169 int bytesRead = -1; 170 byte[] buffer = new byte[4096]; 171 while ((bytesRead = inputStream.read(buffer)) != -1) 172 { 173 fileOutputStream.write(buffer, 0, bytesRead); 174 } 175 } 176 catch (Exception e) 177 { 178 Log.e(TAG, "", e); 179 } 180 finally 181 { 182 try 183 { 184 if (inputStream != null) 185 { 186 inputStream.close(); 187 } 188 189 if (httpURLConnection != null) 190 { 191 httpURLConnection.disconnect(); 192 } 193 194 if (fileOutputStream != null) 195 { 196 fileOutputStream.flush(); 197 fileOutputStream.close(); 198 } 199 } 200 catch (Exception e) 201 { 202 Log.e(TAG, "", e); 203 } 204 } 205 }
測試結果以下:編程
下載文件:360MobileSafe_4.3.5beta.apk 連接:http://msoftdl.360.cn/mobilesafe/shouji360/360safesis/360MobileSafe_4.3.5beta.apk 大小:12.65MB瀏覽器
測試結果: DefaultHttpClient平均耗時:7275ms(第一次) 3861ms(第二次) HttpURLConnection平均耗時:5445ms(第一次) 3119ms(第二次)服務器
HttpURLConnection傳輸效率更高網絡
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ide
下載文件:old offender.apk 連接:http://gdown.baidu.com/data/wisegame/79fb2f638cc11043/oldoffender.apk 大小:4.98MB性能
測試結果: DefaultHttpClient平均耗時:3780ms(第一次) 4008ms(第二次) 4209ms(第三次) HttpURLConnection平均耗時:3718ms(第一次) 4783ms(第二次) 3945ms(第三次)測試
兩者相差無幾google
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下載文件:baidu首頁html 連接:http://www.baidu.com 大小:使用DefaultHttpClient下載的是11.61KB的html(被baidu視爲PC端瀏覽器訪問),使用HttpURLConnection下載的是5.22KB的html(被baidu視爲移動端瀏覽器訪問)
測試結果:無效
說明:這也是某些測試說HttpUrlConnection下載速度快幾倍所使用的連接,其實根本緣由在於這兩API下載的html大小就差了兩倍,比較結果是不公平的
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下載文件:baidu首頁logo 連接:http://www.baidu.com/img/bdlogo.gif 大小:1.54KB
測試結果:無效
說明:因爲文件較小,有時候DefaultHttpClient比HttpURLConnection快不少,而下一秒的測試結果又反過來了,這是由於傳輸時間相差無幾,而鏈接的耗時不肯定,從而致使總耗時相差很大,因此沒法判斷誰的傳輸效率更高。
結論:文件越大,可能HttpUrlConnection的速度優點越明顯,應該是SDK文檔宣稱的GZIP壓縮傳輸致使傳輸時間縮短的緣由,固然,前提是服務器得支持GZIP傳輸~