android-async-http是一个为Android量身定制的异步HTTP请求框架,它基于Apache的HttpClient开发。本文针对v1.4.6版本进行分析。

1. 功能介绍

android-async-http中所有的HTTP请求都在主线程外的其他线程中执行,所有的请求回调都在创建该回调对象的线程中进行,所以不论在什么地方发起请求,系统都能够正确地进行处理。android-async-http的特性总结如下:

  • 异步网络请求,在匿名回调中处理响应
  • 使用线程池来限制并发请求的数量
  • GET/POST请求参数的builder构造
  • Multipart文件上传
  • 较小的体积,仅60KB
  • 自动请求重发优化
  • 支持gzip格式自动解压缩
  • 可选的内置Json解析
  • 可选的Cookie持久化存储

1.1 基本使用

android-async-http的使用比较简单,实例化一个AsyncHttpClient对象,然后调用其get()/post()等方法传入URL和请求参数还有一个回调处理对象,就可以发送HTTP请求。

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {@Overridepublic void onStart() {// called before request is started}@Overridepublic void onSuccess(int statusCode, Header[] headers, byte[] response) {// called when response HTTP status is "200 OK"}@Overridepublic void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {// called when response HTTP status is "4XX" (eg. 401, 403, 404)}@Overridepublic void onRetry(int retryNo) {// called when request is retried}
});

2. 总体设计

2.1 概述

android-async-http的结构比较简单,整体可以分解成三层,最上一层负责由客户端代码调用发送请求,第二层负责请求的封装和执行,最下一层负责处理HTTP响应。

  • AsyncHttpClient:调用此客户端类中的方法发送异步HTTP请求。
  • RequestParams:HTTP请求参数集合,可包含文件和数据流。
  • AsyncHttpRequest:代表异步HTTP请求,作为线程执行对象。
  • AsyncHttpResponseHandler:提供基本的HTTP响应处理。
  • RequestHandle:HTTP请求的句柄,用于取消请求。

2.2 工作流程

客户端调用AsyncHttpClient中的方法,传入URL和请求参数RequestParams发送请求,请求被封装成一个AsyncHttpRequest对象,这个对象代表一个异步请求,把请求加入到队列中等待执行,执行请求的过程中通过调用客户端传入的回调接口,发送消息通知客户端请求执行的情况。

3. 详细设计

android-async-http框架建立在Apache的HttpClient库之上,对HttpClient的类库进行了包装和升级,诸如HTTP请求失败重试机制,multipart/form-data和Json请求体的支持,HTTP响应的处理与包装。

此外还针对Android平台的一些特性进行优化,包括利用线程池技术执行HTTP请求以避免阻塞UI线程,在请求响应时利用Android的消息机制在UI线程执行处理代码,还利用了SharedPreferences持久化存储Cookie。

3.1 发送HTTP请求

AsyncHttpClient是框架中的核心类,所有的HTTP请求都通过这个类发送。它有一系列get()post()put()delete()head()方法,分别代表HTTP协议的GET,POST,PUT,DELETE,HEAD请求。这些方法最终都会调用sendRequest()方法,这个方法会把一个HTTP请求包装成一个线程对象放入请求队列等待执行。

AsyncHttpRequest request = newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context);
threadPool.submit(request);

newAsyncHttpRequest()方法创建一个AsyncHttpRequest对象,AsyncHttpRequest类实现了Runnable接口,它代表一个异步请求,在run()方法中实现了具体的HTTP访问。

发送请求的流程图如下:

3.2 取消HTTP请求

sendRequest()方法中,当把AsyncHttpRequest对象提交之后,会创建一个HTTP请求的句柄RequestHandle,之后作为返回值返回。

通过这个句柄可以操纵这个HTTP请求,句柄类中提供了cancel()方法可以取消这个请求,这个方法委托调用AsyncHttpRequestcancel()方法,在HTTP请求的执行过程中,设置了许多检查点,如果在执行过程中检测到取消标识,则发送通知给回调对象,并且终止HTTP请求的执行。

除了可以取消某个具体的请求,android-async-http还支持把一个HTTP请求对象和Android中的Context绑定,通过绑定Context,可以对一个Context相关的所有请求执行一些操作,例如,可以在ActivityonDestroy()方法中可以取消与在Activity中创建的所有请求。

private final Map<Context, List<RequestHandle>> requestMap;

AsyncHttpClient类中声明了一个成员requestMap,它关联了Context和HTTP请求的句柄,在构造方法中对其进行初始化。

每次调用sendRequest()方法发送HTTP请求,如果传入的Context参数不为null,都会把这个请求句柄添加到Context相关的句柄链上。

AsyncHttpClient中有两个方法:cancelAllRequest(boolean)cancelRequests(Context, booolean),前一个方法取消系统中所有的请求,后一个方法取消一个Context下的所有请求。

3.3 HTTP请求参数

RequestParams类封装了HTTP请求参数的集合,在这个类中有大量put()方法,用于添加各种请求参数和请求实体。

发送GET或DELETE请求时,调用getParamString()方法把请求参数拼装成URL中的查询字符串;而发送POST或PUT请求时,调用getEntity()方法获取请求实体,RequestParams支持三种类型的请求实体:

  1. Json
  2. multipart/form-data
  3. url-encoded pairs

3.3.1 multipart/form-data请求体

multipart/form-data请求的基础方法是POST,它的请求头和请求体与普通的POST请求不同。普通的POST请求只能发送简单的name-value对,而使用multipart/form-data可以对请求体进行包装可以发送多个不同种类的请求体内容。

android-async-http对多文件上传的支持,就是使用multipart/form-data格式对文件数据进行包装。

SimpleMultipartEntity类继承自HttpEntity类,这个类实现了对multipart/form-data格式请求体的封装。

关于multipart/form-data请求的协议细节不多作介绍。

3.3.2 Json请求体

android-async-http还支持把请求参数包装成Json格式的请求体,JsonStreamerEntity类继承自HttpEntity类,这个类实现了把请求参数包装成Json格式的数据,可以用来上传文件和二进制数据。

3.4 执行HTTP请求

AsyncHttpRequest类代表一个异步HTTP请求,它封装了执行HTTP请求的具体细节,并实现了Runnable接口,作为线程执行对象,以异步的方式进行HTTP访问。

执行请求的流程图如下:

makeRequest()方法中完成HTTP访问,makeRequestWithRetries()方法调用makeRequest()方法,封装了对异常的处理逻辑,并实现了请求的重试机制。

HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();

HttpRequestRetryHandler是Apache HttpClient提供的HTTP请求重发的处理接口,调用retryRequest()方法申请一次HTTP请求重发,如果retryRequest()返回true即表示申请通过可以发送,false反之。

android-async-http实现了自己的重发处理器RetryHandler,在AsyncHttpClient的构造方法做了初始化,默认最多重发5次,每次间隔1.5s。

httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_MAX_RETRIES, DEFAULT_RETRY_SLEEP_TIME_MILLIS));

3.4.1 重发处理机制

RetryHandler类中维护了一个黑白名单,黑白名单中存储了异常类型,每次请求发送失败都会抛出一个异常,根据这个黑白名单判断是否重发请求。

调用retryRequest()方法传入一个异常对象和一个整数,异常对象是在进行HTTP访问时抛出的,整数表示请求重发的次数。在RetryHandler类的实现中,retryRequest()方法根据重发的次数和抛出的异常还有其它一些属性,响应重发请求。

makeRequestWithRetries()方法的实现中,利用一个while循环实现请求重发的机制。

请求重发的流程图如下:

3.5 处理HTTP响应事件

ResponseHandlerInterface接口用于发送消息通知客户端代码处理请求执行过程发送的事件(请求的过程中会发送很多事件,包括开始事件、结束事件、成功事件、失败事件、重发事件、取消事件、更新进度事件),它是一个处理HTTP响应的回调接口。AsyncHttpResponseHandler类是这个接口的直接实现,这个类实现了最基本的事件处理逻辑,还有很多其它具体的处理类都是基于这个类的包装了几个接口,以满足一些特殊的需求。

HTTP请求事件的处理有两种方式:同步和异步,同步方式会在执行请求的线程中直接调用回调方法,而异步方式则会在创建这个处理对象的线程中调用回调方法。

ResponseHandlerInterface接口中定义了一系列sendXXX()方法,这些方法在请求执行过程中被调用,用于发送事件,在AsyncHttpResponseHandler的实现中,这些sendXXX()方法调用了sendMessage()方法,sendMessage()方法中封装了选择同步或异步处理的逻辑。

protected void sendMessage(Message msg) {if (getUseSynchronousMode() || handler == null) {handleMessage(msg);} else if (!Thread.currentThread().isInterrupted()) { // do not send messages if request has been cancelledAssertUtils.asserts(handler != null, "handler should not be null!");handler.sendMessage(msg);}
}

handleMessage()方法模仿了Handler中的处理方法,在这个方法里面实现了具体的事件分发,根据事件类型调用相应的回调接口。

同步方式直接调用handleMessage()方法在当前线程中执行处理;异步方式使用了Handler,在构造方法中使用一个构造线程的Looper对象初始化了这个Handler,事件的处理委托给Handler进行。

处理请求事件的流程图如下:

框架中其它处理类都继承自AsyncHttpResponseHandler,例如:TextHttpResponseHandlerFileAsyncHttpResponseHandler,前者把二进制数据流编码成字符串作为结果返回,后者把HTTP请求返回的结果写入到文件,把文件对象作为结果返回。

3.6 持久化Cookie存储

PersistentCookieStore类实现了Apache HttpClient的CookieStore接口,它通过SharedPreferences实现了Cookie在Android设备上的持久化存储。

Cookie持久化的技术上,利用了Java的序列化机制,提供了一个Cookie包装类:SerializableCookie,这个包装类实现了Serializable接口。PersistentCookieStore类提供了对二进制字节数组和十六进制字符串的编码和解码方法。

添加时利用序列化机制把Cookie转换成字节数组然后进行十六进制编码,再存储到SharedPreferences中;读取时先进行逆向解码,再利用对象输入流ObjectInputStream获取Cookie对象。

本文出自2dxgujun,转载时请注明出处及相应链接。

android-async-http 源码分析相关推荐

  1. CTS(11)---android自动化测试CTS源码分析之一

    android自动化测试CTS源码分析之一 1, 概述 CTS(Compatibility Test Suite)全名兼容性测试,主要目的就是让Android设备开发商能够开发出兼容性更好的andro ...

  2. android agps,Android应用开发Android GPS ——AGPS源码分析及配置

    本文将带你了解Android应用开发Android GPS --AGPS源码分析及配置,希望本文对大家学Android有所帮助. " Android Framework GPS --AGPS ...

  3. android gps源码分析,Android编程之Android GPS ——AGPS源码分析及配置

    本文主要介绍了Android编程的Android GPS --AGPS源码分析及配置,通过具体的分析以及源码,向大家展示了这些,希望对大家学习Android编程有所帮助. 1:冷启动指令: locat ...

  4. android(cm11)状态栏源码分析(一)

    版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/50216563 (一):写在前面 最近由于工 ...

  5. Android 7.0 源码分析项目一期竣工啦

    从 Android 入行开始,因为工作需求和解决疑难bug的原因陆陆续续的看过一些源码,但都不成系统,从2016年年底开始,在Github上建了一个Android Open Source Projec ...

  6. Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)

    1.先熟悉handler方式实现主线程和子线程互相通信方式,子线程和子线程的通信方式 如果不熟悉或者忘记了,请参考我的这篇博客     Android之用Handler实现主线程和子线程互相通信以及子 ...

  7. 线程中task取消_Rust Async: async-task源码分析

    async-std是rust异步生态中的基础运行时库之一,核心理念是合理的性能 + 用户友好的api体验.经过几个月密集的开发,前些天已经发布1.0稳定版本.因此是时候来一次深入的底层源码分析.asy ...

  8. Android之AsyncTask源码分析(第五篇:execute方法只能执行一次的原因)

    (注意:本文基于API 28的源码分析,API 29上或其他平台的源码略有不同) 前言 当你调用AsyncTask对象的execute()方法时,突然发生崩溃--内心充满不解:java.lang.Il ...

  9. Android——RIL 机制源码分析

    Android 电话系统框架介绍 在android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BP,BP接收到信息后又通过rild传送给AP.AP与BP之间有两种通信方式: 1. ...

  10. Android屏幕刷新——源码分析

    Android屏幕刷新原理--源码分析 文章目录 Android屏幕刷新原理--源码分析 概述 VSync信号 三级缓冲 源码分析 消息队列的同步屏障 参考资料 概述 Android系统每16ms(一 ...

最新文章

  1. 将csv文件导入mysql
  2. 云白条,做有温度的金融,帮助有困难的人
  3. Android --- Add Google Maven repository and sync project
  4. Java——线程的四种不同形式
  5. 计算机2018创业方向,推荐2018年创业的方向
  6. 使用matlab播放特定频率的声音
  7. 回文子序列_计算回文子序列的总数
  8. mysql中in的使用
  9. Python学习笔记之文件
  10. 前段基础html常用标签,web前端开发网络课程,HTML常用的五种标签
  11. CloudStack升级中文指南:4.1.x/4.2.x 至4.3版本
  12. R语言期末试题【二期补充】-重庆工商大学-统计学课程
  13. 第三次作业(尤心心)
  14. 《新时代的中国青年》白皮书——一个90后的自白
  15. db2 创建实例,创建数据库,创建表
  16. 操作系统产品密钥查看方法
  17. 美股数据获取 python_几行Python代码,轻松获取美股阿里巴巴的交易数据
  18. 算是我看源码时的一个小技巧吧~
  19. 阿⾥云Apsara Clouder云计算专项技能认证:云服务器ECS⼊门【 个⼈所得税年度应纳税额抵扣 3600(0成本)】
  20. 教你刷各大android手机应用市场下载排名

热门文章

  1. HDU 1247(Hat’s Words )
  2. 去掉一键还原 开机按k键
  3. Google Gears 指南
  4. MTM:matlab实现5主函数解码
  5. 深度学习笔记:windows+tensorflow 指定GPU占用内存(解决gpu爆炸问题)
  6. Ubuntu终端远程连接计算机(Linux)
  7. C语言函数手册:c语言库函数大全|C语言标准函数库|c语言常用函数查询
  8. 莱斯信道衰落下的QPSK误码率分析
  9. java多态替换switch_第1章 重构,第一个案例(3):运用多态取代switch
  10. [云炬创业管理笔记]第三章打造优秀创业团队讨论1