最近在看 Volley 的源码,发现里面的网络请求方式很有意思,在 Android 2.3 及以上用的是 HttpURLConnection,2.2 及以下用的是 HttpClient。秉着好奇心找到一篇有关的文章,于是便尝试着翻译下来,第一次翻译文章,有什么不足的地方,麻烦指出。
大部分需要联网的 Android 应用程序都会使用 HTTP 去发送和接收数据。Android 中包括两种方式来进行 HTTP 的请求:HttpURLConnection 和 HttpClient。两种方式都支持 HTTPS、数据流上传和下载、配置超时时间、Ipv6 和连接池。
HttpClientDefaultHttpClient 和它同级的 AndroidHttpClient 都是很适合 web 浏览器的可拓展的 HTTP 客户端。他们有着众多的 API 而且十分灵活,同时也十分的稳定,极少有 bug。
但是由于 API 的数量过多,使得我们很难在不破坏兼容性的情况下对其进行拓展。而且 Android 团队对于 HttpClient 也不是很积极。
HttpUrlConnectionHttpURLConnection 是一个适用于大多数应用程序的、通用的轻量级 HTTP 客户端。它提供的 API 比较简单,但它主要的 API 使我们能轻易的使用和拓展它。
在 Android 2.2 之前,HttpURLConnection 有着很多让人厌烦的 bug。特别是,在一个可读的 InputStream 中调用 close() 方法能让连接池失效。我们可以通过禁用连接池来解决这个问题:
private void disableConnectionReuseIfNecessary () { // HTTP 连接重用,这是 Android 2.2 之前的一个 bug if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { System.setProperty("http.keepAlive", "false"); } }
在 Android 2.3,我们添加了透明的响应缓存。HttpURLConnection 将会自动在每个发出的请求中加入消息头,以及处理相应的返回结果:「Accept - Encoding:gzip」
通过配置你的 Web 服务器来支持对客户端的响应结果进行压缩的功能,从而获取最大的好处。如果响应压缩有问题,这篇文档 将显示如何禁用它。
自从 HTTP 的请求头 content-Length 返回压缩的大小之后,使用 getContentLength() 来作为未压缩数据的缓冲区是错误的。而应该从响应中读取字节,直到 InputStream.read() 返回 -1。
我们而在 Android 2.3 中为 HTTPS 做了很多的改进。HttpsURLConnection 尝试连接服务器名称指示(SNI),允许多个 HTTPS 主机共享一个 IP 地址,同时也启用了压缩和会话机制。如果连接失败了,它会自动去重新连接。这使得 HttpsURLConnection 在连接到最新服务器时更加有效,而且并不会破坏旧版服务器的兼容性。
在 Android 4.0,我们可以添加一个响应缓存。当缓存被安装之后,HTTP 请求都会同时满足这三种情况:
所有的缓存响应都直接由本地存储提供。因此没有必要去发起网络连接,这些响应都可以直接获取到。得视情况而定的缓存响应必须由网络服务器来检查更新。客户端发送一个像 “如果 /foo.png 这张图片改变了,请将它给我”,然后客户端将会回复更新后的内容或者一个「304 Not modified」的状态。如果内容并没有改变,客户端就不会下载任何内容。从网络中提供未缓存的响应。这些响应将被存储在响应缓存中以供以后使用。使用反射在支持它的设备上启用 HTTP 的响应缓存。示例代码将会打开 Android 4.0 的响应缓存,而不会影响早期的版本。
private void enableHttpResponseCache(){ long httpCacheSize = 10 * 1024 * 1024; // 10 MB File httpCacheDir = new File(getCacheDir(), "http"); try { Class.forName("android.net.http.httpResoonseCache") .getMethod("install", File.class, long.class) .invoke(null, httpCacheDir, httpCacheSize); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrac(nmsl是什么意思?nmsl原本是骂人的词(母亲去世),被黑粉带节奏,翻译成了never mind the scandal and liber(永远不要理会谣言和重伤)。因此,不少网友原本不知道该词的意思,还都以为是一个正能量的好词。)e(); } }
你应该配置你的 Web 服务器来在它的 HTTP 响应中设置缓存的消息头。
哪一种方式是最好的?HttpClient 在 Android 2.2 之前拥有比较少的 bug,因此选择它是最好的选择。
在 Android 2.3 及以后,HttpURLConnection 是最好的选择。它那简单的 API 以及小尺寸使其非常适合 Android。透明的压缩和响应缓存减少了网络的使用,提高速度以及节省电量。新的应用程序中应使用 HttpURLConnection。我们未来也会将更多的精力花在优化 HttpURLConnection 上面。