前言

目前基本上每个应用都会使用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. hbuilder用自己的服务

    2016-03-10 以后写测试demo用Sublime3 http://docs.emmet.io/cheat-sheet/ 更多炫酷信息和emmet语法请参见: 视频demo 语法文档 2016- ...

  2. SQL 有父标识的 递归查询

    递归查询,临时表的高级应用 WITH temp AS ( --父项 SELECT * FROM Ar_Area WHERE Ar_Parent = UNION ALL --递归结果集中的下级 SELE ...

  3. JamCam创业故事:辞掉工作,去开发一个应用

    编者按:这是JamCam创始人的自述.这家初创公司提供的应用很简单,但是极为成功:有了JamCam,你所录制的视频会自动添加你正在iPhone中聆听的音乐,作为视频的背景音乐.和朋友分享时是不是方便多 ...

  4. 网卡添加VLAN TAG

    #modprobe 8021q 用命令 lsmod | grep 8021q 来检查 以配置网卡eth0为例,添加vlan号:1002 ================================ ...

  5. HOW TO: Creating your MSI installer using Microsoft Visual Studio* 2008

    Quote from: http://software.intel.com/en-us/articles/how-to-creating-your-msi-installer-using-visual ...

  6. Mysql备份数据库的一种方法

    今天添加了一个数据库自动备份的模块,mysql数据备份的方法有很多,可以对单个数据库备份,可以多个数据库备份,也可以对某一个表进行备份,可以只备份数据库的结构不备份数据,可以根据需要做不同处理,正好现 ...

  7. [翻译][MVC 5 + EF 6] 3:排序、过滤、分页

    原文:Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application 1.添加排序: 1. ...

  8. c#中创建类(更新中)

    类是最常见的一种引用类型,最简单的定义如下 class YouClassNam {} 复杂的类可能包含一下内容 类属性 类属性以及类修饰符.  非嵌套的类修饰符有:public,internal,ab ...

  9. SimpleXML解析xml文件

    SimpleXML 扩展提供了一种获取 XML 元素的名称和文本的简单方式. 与 DOM 或 Expat 解析器相比,SimpleXML 仅仅用几行代码就可以从 XML 元素中读取文本数据. Simp ...

  10. thinkphp分页格式的完全自定义,直接输入数字go到输入数字页

    实现分页效果如下: 以下标注红色字体的为重点   找到文件page.class.php在ThinkPHP/Library/Thinkpage.class.php并打开文件,复制函数show,在本文件中 ...