Android平台上的大多数联网应用都使用HTTP来发送和接收数据。Android平台包括两种HTTP client:HttpURLConnection和Apache HTTP Client。两者都支持HTTPS、流上传/下载、超时时间设置、IPV6及连接池。
Apache HTTP Client
DefaultHttpClient及 AndroidHttpClient都是针对Web浏览器的可扩展的HTTP clients。它们拥有数量庞大大且灵活的API,而且它们的实现都比较稳定,但是都有一些bug。
不过,由于它们数量庞大的API导致我们无法在不破坏它们兼容性的情况下改进它们。所以Android开发团队并不热衷于Apache HTTP Client。
HttpURLConnection
HttpURLConnection是一个针对一般用途的轻量级的HTTP client,并适用于大多数Android应用。这个类有一个比较低调的开始,不过它特别关注的那些API使我们可以简单、稳定的改进它。
在Froyo(Android2.2)版本之前,HttpURLConnection有一些让人十分沮丧的bugs。特别是当我们在一个可读的InputStream上调用close()时,会破坏连接池。我们可以通过禁用连接池来规避这个问题(代码如下):
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(Android2.3)中,我们新增了透明的相应压缩(原文是:we added transparent response compression.哪位大神知道正确翻译是啥的话,帮忙提醒下 -。-)。HttpURLConnection 会自动在它发出的请求中添加一个header,并且会处理对应的响应。
Accept-Encoding: gzip
你可以通过配置你的Web服务器来压缩返回给客户端的响应,从而利用该新特性。如果压缩后的响应有异常,可以在这个类的api文档中查看如何禁用该特性。
尽管HTTP的Content-Length头中返回了压缩后的大小,但是使用getContentLength()的返回值来设定那些未压缩数据的buffer是一个错误。因此,我们应该从响应中读取每一个字节直到InputStream.read()返回-1。
在Gingerbread(Android2.3)中,我们还针对HTTPS做了一些提升。HttpURLConnection尝试与 Server Name Indication (SNI)进行互联,这是一种允许多个HTTPS host共享一个IP地址的技术。同时还使用压缩及session tickets。假如HttpURLConnection连接失败,HttpURLConnection会去掉以上特性后自动尝试重新连接。这使得HttpURLConnection在不破坏与旧的server兼容性的情况下,连接up-to-date servers更高效。
在Ice Cream Sandwich(Android4.0)中,我们正在添加一个response cache。应用这个特性,HTTP请求会以下列三种情况被响应:
1、完全缓存的响应,直接从本地获取。这种状况下完全不需要联网,并且可以立即响应。
2、有条件的被缓存的响应,这些缓存是否需要刷新需要从服务器确认。客户端发送一个类似“昨天以来,如果foo.png发生过变动,就给我一个新的”这样的请求,服务器会返回一个新的图片或者一个304 Not Modified状态吗给客户端。假如请求的内容没有变动,则内容不会被再次下载。
3、没有缓存的响应,从服务器获取。这种响应会被缓存起来以备以后使用。
可以通过反射来开启那些支持缓存HTTP响应的设备上的缓存功能。下面的代码演示了如何在不影响Ice Cream Sandwich(Android4.0)以前的版本的情况下开启缓存功能。
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) {
}
}
你应该总是配置你的Web服务器以便在HTTP响应的头中设置与缓存相关的内容。
什么是最好的HTTP client
在Froyo(Android2.2)及更早期的版本中,Apache HTTP client相对于HttpURLConnection 拥有更少的bug。所以这种情况下Apache HTTP clien是最好的选择。
从Gingerbread(Android2.3)开始,HttpURLConnection则是最好的选择。它简单的API和比较小的体积使他更适合Android。Transparent compression和响应缓存则减少了网络使用,提升了加载速度和电池性能。新的应用应该使用HttpURLConnection,同时HttpURLConnection也是我们以后的工作重心所在。