资讯专栏INFORMATION COLUMN

Android实战之你应该使用哪个网络库?

WelliJhon / 2198人阅读

摘要:网络库对比获得了巨大的社区的支持,以至于最终是将它作为了默认的,并且会在之后弃用。事实上,从开始,所有的网络操作都必须强制在多带带的线程中进行。到现在,我发现应该把这些网络库的关系表述在一张图中。

本篇为翻译文章 原文地址这里

如果正在学习Android,建议可以参考笔者的我的编程之路——知识管理与知识体系

[TOC]

前言

目前基本上每个应用都会使用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(), 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> 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做了一个比较,其性能对比如下:

图片加载库对比

另一方面,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有三层不同的缓存:两层在内存中,以及一层在内部存储中。

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/12434.html

相关文章

  • fir.im Weekly - 揭秘直播移动 APP 技术实现

    摘要:本次分享将为大家揭开移动直播核心技术的神秘面纱。中文翻译链接英文原文阅读,点击这里。视频直播初窥高仿喵播总结了自己对于当下直播现状的认识,分享了高仿高仿喵播的项目技术实现,非常详细。 2016年直播似乎无处不在,作为一个开发者也许需要补充下关于直播技术点。本期 fir.im Weekly 整理了一些开发者对于直播实践项目中的技术经验与直播技术架构分析等内容,还有一些关于 iOS 、An...

    you_De 评论0 收藏0
  • fir.im Weekly - 揭秘直播移动 APP 技术实现

    摘要:本次分享将为大家揭开移动直播核心技术的神秘面纱。中文翻译链接英文原文阅读,点击这里。视频直播初窥高仿喵播总结了自己对于当下直播现状的认识,分享了高仿高仿喵播的项目技术实现,非常详细。 2016年直播似乎无处不在,作为一个开发者也许需要补充下关于直播技术点。本期 fir.im Weekly 整理了一些开发者对于直播实践项目中的技术经验与直播技术架构分析等内容,还有一些关于 iOS 、An...

    Ryan_Li 评论0 收藏0
  • fir.im Weekly - 揭秘直播移动 APP 技术实现

    摘要:本次分享将为大家揭开移动直播核心技术的神秘面纱。中文翻译链接英文原文阅读,点击这里。视频直播初窥高仿喵播总结了自己对于当下直播现状的认识,分享了高仿高仿喵播的项目技术实现,非常详细。 2016年直播似乎无处不在,作为一个开发者也许需要补充下关于直播技术点。本期 fir.im Weekly 整理了一些开发者对于直播实践项目中的技术经验与直播技术架构分析等内容,还有一些关于 iOS 、An...

    stdying 评论0 收藏0
  • 安卓新建项目 - 收藏集 - 掘金

    摘要:经也要热更新掘金本文同步自的地方酒馆好久没写博客了。好了,说了这么多还没见到图从零开始搭建一个项目第章掘金鸡汤成功其实很简单,定下一个合理的计划,然后坚持按照计划执行。 用RecyclerView展示错误和空白界面 附加详情界面实践-MultiItem进阶 | 掘金技术征文 - 掘金前言 本文是MultiItem系列的进阶文章,讲解如何展示空白、错误等状态页,这个功能比较常用,实现的思...

    Sanchi 评论0 收藏0
  • 金三银四,2019大厂Android高级工程师面试题整理

    摘要:原文地址游客前言金三银四,很多同学心里大概都准备着年后找工作或者跳槽。最近有很多同学都在交流群里求大厂面试题。 最近整理了一波面试题,包括安卓JAVA方面的,目前大厂还是以安卓源码,算法,以及数据结构为主,有一些中小型公司也会问到混合开发的知识,至于我为什么倾向于混合开发,我的一句话就是走上编程之路,将来你要学不仅仅是这些,丰富自己方能与世接轨,做好全栈的装备。 原文地址:游客kutd...

    沈建明 评论0 收藏0

发表评论

0条评论

WelliJhon

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<