Android 中HttpClient和HttpURLConnection选取

原文地址:http://android-developers.blogspot.com/2011/09/androids-http-clients.html

译文:http://yunfeng.sinaapp.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变得一样强大和复杂了 ! \(^o^)/~
posted @ 2014-01-21 16:48  似水流云  阅读(278)  评论(0编辑  收藏  举报