前言

目前基本上每个应用都会使用HTTP/HTTPS协议来作为主要的传输协议来传输数据。即使你没有直接使用HTTP协议,也会有成堆的SDK会包含这些协议,譬如分析、Crash反馈等等。当然,目前也有很多优秀的HTTP的协议库,可以很方便的帮助开发者构建应用,本篇博文中会尽可能地涵盖这些要点。Android的开发者在选择一个合适的HTTP库时需要考虑很多的要点,譬如在使用Apache Client或者HttpURLConnection时可能会考虑:

  • 能够取消现有的网络请求

  • 能够并发请求

  • 连接池能够复用存在的Socket连接

  • 本地对于响应的缓存

  • 简单的异步接口来避免主线程阻塞

  • 对于REST API的封装

  • 重连策略

  • 能够有效地载入与传输图片

  • 支持对于JSON的序列化

  • 支持SPDY、HTTP/2

历史回眸

最早的时候Android只有两个主要的HTTP客户端: HttpURLConnection, Apache HTTP Client。根据Google官方博客的内容,HttpURLConnection在早期的Android版本中可能存在一些Bug:

在Froyo版本之前,HttpURLConnection包含了一些很恶心的错误。特别是对于关闭可读的InputStream时候可能会污染整个连接池。

同样,Google官方并不想转到Apache HTTP Client中:

Apache HTTP Client中复杂的API设计让人们根本不想用它,Android团队并不能够有效地工作。

而对于大部分普通开发者而言,它们觉得应该根据不同的版本使用不同的客户端。对于Gingerbread(2.3)以及之后的版本,HttpURLConnection会是最佳的选择,它的API更简单并且体积更小。透明压缩与数据缓存可以减少网络压力,提升速度并且能够节约电量。当我们审视Google Volley的源代码的时候,可以看得出来它也是根据不同的Android版本选择了不同的底层的网络请求库:

全选复制放进笔记
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}

不过这样会很让开发者头疼,2013年,Square为了解决这种分裂的问题发布了OkHttp。OkHttp是直接架构与Java Socket本身而没有依赖于其他第三方库,因此开发者可以直接用在JVM中,而不仅仅是Android。为了简化代码迁移速度,OkHttp也实现了类似于HttpUrlConnection与Apache Client的接口。

网络库对比

OkHttp获得了巨大的社区的支持,以至于Google最终是将它作为了Android 4.4默认的Engine,并且会在5.1之后弃用Apache Client。目前OkHttp V2.5.0支持如下特性:

  • HTTP/2 以及 SPDY的支持多路复用

  • 连接池会降低并发连接数

  • 透明GZIP加密减少下载体积

  • 响应缓存避免大量重复请求

  • 同时支持同步的阻塞式调用与异步回调式调用

笔者关于OkHttp最喜欢的一点是它能够将异步请求较好的展示:

全选复制放进笔记
private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build(); client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, Throwable throwable) {
throwable.printStackTrace();
} @Override
public void onResponse(Response response) throws IOException {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
});
}

这个用起来非常方便,因为往往大的数据请求都不能放置在UI主线程中进行。事实上,从Android 3.0(Honeycomb 11)开始,所有的网络操作都必须强制在单独的线程中进行。在当时如果要把HttpUrlConnection和AsyncTask结合起来使用,还是比较复杂的。而2013年的Google I/O大会上,Google提出了Volley,一个提供了如下便利的HTTP库:

  • Automatic scheduling of network requests.

  • Multiple concurrent network connections.

  • Transparent disk and memory response caching with standard HTTP cache coherence.

  • Support for request prioritization.

  • Cancellation request API. You can cancel a single request, or you can set blocks or scopes of requests to cancel.

  • Ease of customization, for example, for retry and backoff.

  • Strong ordering that makes it easy to correctly populate your UI with data fetched asynchronously from the network.

  • Debugging and tracing tools.

Volley主要架构在HttpUrlConnection之上,如果希望能够抓取图片或者JSON数据,Volley有自定义的抽象类型ImageRequest与JsonObjectRequest,可以自动转化为HTTP请求。同时,Volley也有一个硬编码的网络连接池大小:

全选复制放进笔记
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;

不过OkHttp可以自定义连接池的大小:

全选复制放进笔记
private int maxRequests = 64;
private int maxRequestsPerHost = 5; executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));

在某些情况下,OkHttp可以通过使用多线程来有更好的性能体现。不过如果现有的程序中已经用Volley做了顶层封装,那么也可以使用HttpStack implementation点击预览这个来使用OkHttp的请求与响应接口来替换HttpUrlConnection。

到这里已经可以发现,OkHttp本质上是自定义了一套底层的网络请求架构。目前HTTP客户端已经逐步转化为了支持大量图片,特别是那种无限滚动与图片传输的应用。同时,REST API已经成为了业界标准,基本上每位开发者都需要处理大量标准化的任务,类似于JSON序列化与将REST请求映射到Java的接口上。Square也在不久之后针对这两个问题提出了自己的解决方案:

  • Retrofit - 一个类型安全的HTTP客户端支持REST接口

  • Picasso - 针对Android的图片下载与缓存库

Retrofit 提供了一个面向Java代码与REST接口之间的桥接,可以迅速将HTTP API转化到Java接口中并且自动生成带有完整文档的实现:

全选复制放进笔记
public interface GitHubService {
@GET("/users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
} Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.build(); GitHubService service = retrofit.create(GitHubService.class);

除此之外,Retrofit 也支持面向JSON、XML以及Protocol Buffers的数据转化。在另一篇博客中将AsyncTask与Volley以及Retrofit做了一个比较,其性能对比如下:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" alt="" data-src="http://i.imgur.com/tIdZkl3.png" />

图片加载库对比

另一方面,Picasso是一个专门的面向图片任务的HTTP库。譬如,可以用一行代码就把网络图片加载到ImageView中:

全选复制放进笔记
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

Picasso与Retrofit都是默认的使用OkHttpClient作为底层的HTTP客户端,然而,你也可以配置自己的基于HttpUrlConnection的客户端。

Glide是一个非常类似于Picasso的库,不过它提供了一些额外的功能,譬如GIF动画、简略图生成以及视频。

Facebook开源的它们自己的图片加载库Fresco使用了它们自定义的Android客户端。其中它的一个非常优秀的特性在于Fresco的面向Bitmaps的自定义才存储策略能够避免JVM堆顶的垃圾回收的限制。Fresco是分配了Android中被称为ashmem部分的内存,同时,它用了一些方法允许同时从Java以及C++代码访问ashmem部分,来进行NDK级别的CPU处理。为了节省数据存储空间以及CPU的消耗,Fresco有三层不同的缓存:两层在内存中,以及一层在内部存储中。

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" alt="" data-src="https://scontent-lax3-1.xx.fbcdn.net/hphotos-xpt1/t39.2365-6/11057083_393469260836543_318035251_n.png" />

到现在,我发现应该把这些网络库的关系表述在一张图中。正如你可以看见的,HTTP的传输组件存在于示意图的底部,与所有上层的库进行交互。你可以选择单纯的HttpUrlConnection或者最新的OkHttpClient客户端。

Resources

  1. Square open source http://square.github.io
  2. Fresco library http://frescolib.org
  3. Volley documentation https://developer.android.com/training/volley
  4. Volley vs Retrofit http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit
  5. Picasso vs. Glide comparison
  6. StackOverflow thread on OkHTTP, Retrofit, Volley
  7. Jake Wharton presentations

原文:http://segmentfault.com/a/1190000003965158

https://packetzoom.com/blog/which-android-http-library-to-use.html

Android实战之你应该使用哪个网络库?的更多相关文章

  1. 【Android实战】----从Retrofit源代码分析到Java网络编程以及HTTP权威指南想到的

    一.简单介绍 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明确为什么Retrofit那么屌. 近期也看了一些其源代码分析的文章以及亲自查看了源代码 ...

  2. [置顶] 【Android实战】----从Retrofit源码分析到Java网络编程以及HTTP权威指南想到的

    一.简介 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明白为什么Retrofit那么屌.最近也看了一些其源码分析的文章以及亲自查看了源码,发现其对 ...

  3. 9套Android实战经典项目资料分享给大家

    通过项目学习收获更大. 1.基于Android平台实战爱短信项目 下载地址:http://pan.baidu.com/s/1hr8CEry 2.Android平台实战CRM客户关系管理(AChartE ...

  4. Android实战技巧:深入解析AsyncTask

    AsyncTask的介绍及基本使用方法 关于AsyncTask的介绍和基本使用方法可以参考官方文档和Android实战技巧:多线程AsyncTask这里就不重复. AsyncTask引发的一个问题 上 ...

  5. 【Android实战开发】3G技术和Android发展简介

    随着移动设备的不断普及和发展,相关软件的开发也越来越受到人们的关注,其中要提及的就是Android开发.本系列博客主要为大家介绍Android的开发,可能会有人问:现在互联网上已经有很多的Androi ...

  6. 【Android实战】记录自学自己定义GifView过程,能同一时候支持gif和其它图片!【有用篇】

    之前写了一篇博客.<[Android实战]记录自学自己定义GifView过程,具体解释属性那些事! [学习篇]> 关于自己定义GifView的,具体解说了学习过程及遇到的一些类的解释,然后 ...

  7. Android实战:手把手实现“捧腹网”APP(二)-----捧腹APP原型设计、实现框架选取

    Android实战:手把手实现"捧腹网"APP(一)-–捧腹网网页分析.数据获取 Android实战:手把手实现"捧腹网"APP(二)-–捧腹APP原型设计.实 ...

  8. Android实战:手把手实现“捧腹网”APP(一)-----捧腹网网页分析、数据获取

    Android实战:手把手实现"捧腹网"APP(一)-–捧腹网网页分析.数据获取 Android实战:手把手实现"捧腹网"APP(二)-–捧腹APP原型设计.实 ...

  9. 利用百度词典API和Volley网络库开发的android词典应用

     关于百度词典API的说明,地址在这里:百度词典API介绍 关于android网络库Volley的介绍说明,地址在这里:Android网络通信库Volley 首先我们看下大体的界面布局!

随机推荐

  1. 一个react的完整项目展示

    和一些人的关系像平行线,一辈子相守相望,见于眼底藏于心间.就怕耐不住寂寞,冲动而成了相交线,在一个点尽情拥抱,从此便离得越来越远,再也不见.遇到这样的人,因为不想做恋人只能一时,所以才选择做朋友能一世 ...

  2. ACM——大数相加

    大数加法 时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte 总提交:2085            测试通过:543 描述 求两个非负整数( ...

  3. 04_过滤器Filter_04_Filter生命周期

    [Filter生命周期] [init(FilterConfig filterConfig) throws ServletException] *和Servlet程序类似,Filter的创建和销毁由we ...

  4. mysql中 出现No query specified

    Mysql----error:no query specified mysql下抛出错误: error:no query specified 出现此错误是sql不合法原因: 如:select * fr ...

  5. 【原创】Linux 增加系统调用

    Linux 增加系统调用大致步骤: 1.下载好内核文件,在内核源文件中添加好自己的调用函数. 2.编译内核 3.验证. 一.在内核源文件中增加自己的函数   首先将内核文件移至/usr/src/下并解 ...

  6. jquery 中的 $("#id") 与 document.getElementById("id") 的区别

    以前没注意过,认为jquery 中的 $("#air") 与 document.getElementById("air") 是一回事,指的是同一个东西.在今天写 ...

  7. 基于IAccessible接口的QQ窗口信息获取的实现

    这个技术现在已经封装成DLL免费开放给大家使用了,详情请加群221487171 可以访问官方网站下载 http://www.guihelper.com/ 主要技术(Microsoft Active A ...

  8. PL/SQL学习(二)条件和循环语句

      原文参考:http://plsql-tutorial.com/   PLSQL条件语句 IF THEN ELSE STATEMENT 1) IF condition THEN  statement ...

  9. 尝试一下用MARKDOWN嵌入代码

    public void test(){ // }

  10. 解决IE6下不支持 png24的透明图片问题

    常用的两种解决方案: 第一:使用IE滤镜解决 关键代码: css代码  _background:none;_filter:progid:DXImageTransform.Microsoft.Alpha ...