HttpClient与HttpUrlConnection下载速度比较

  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传输~