android-async-http 源码分析

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() {

    @Override
    public void onStart() {
        // called before request is started
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // called when response HTTP status is "200 OK"
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
    }

    @Override
    public void onRetry(int retryNo) {
        // called when request is retried
    }
});

2. 总体设计

structure

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访问。

发送请求的流程图如下:send request

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访问。

执行请求的流程图如下:request running

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循环实现请求重发的机制。

请求重发的流程图如下:make request with retries

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 cancelled
        AssertUtils.asserts(handler != null, "handler should not be null!");
        handler.sendMessage(msg);
    }
}

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

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

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

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

3.6 持久化Cookie存储

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

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

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


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

Asynchronous Http Client for Android Build Status An asynchronous, callback-based Http client for Android built on top of Apache's HttpClient libraries. Changelog See what is new in version 1.4.9 released on 19th September 2015 https://github.com/loopj/android-async-http/blob/1.4.9/CHANGELOG.md Javadoc Latest Javadoc for 1.4.9 release are available here (also included in Maven repository): https://loopj.com/android-async-http/doc/ Features Make asynchronous HTTP requests, handle responses in anonymous callbacks HTTP requests happen outside the UI thread Requests use a threadpool to cap concurrent resource usage GET/POST params builder (RequestParams) Multipart file uploads with no additional third party libraries Tiny size overhead to your application, only 60kb for everything Automatic smart request retries optimized for spotty mobile connections Automatic gzip response decoding support for super-fast requests Optional built-in response parsing into JSON (JsonHttpResponseHandler) Optional persistent cookie store, saves cookies into your app's SharedPreferences Examples For inspiration and testing on device we've provided Sample Application. See individual samples here on Github To run Sample application, simply clone the repository and run this command, to install it on connected device gradle :sample:installDebug Maven You can now integrate this library in your project via Maven. There are available two kind of builds. releases, maven central https://repo1.maven.org/maven2/com/loopj/android/android-async-http/ Maven URL: https://repo1.maven.org/maven2/ GroupId: com.loopj.android ArtifactId: android-async-http Version: 1.4.9 Packaging: JAR or AAR Gradle repositories { maven { mavenCentral() } } dependencies { compile 'com.loopj.android:android-async-http:1.4.9' } development snapshots https://oss.sonatype.org/content/repositories/snapshots/com/loopj/android/android-async-http/ Maven URL: https://oss.sonatype.org/content/repositories/snapshots/ GroupId: com.loopj.android ArtifactId: android-async-http Version: 1.5.0-SNAPSHOT Packaging: JAR or AAR Gradle repositories { maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } } dependencies { compile 'com.loopj.android:android-async-http:1.5.0-SNAPSHOT' } Documentation, Features and Examples Full details and documentation can be found on the project page here: https://loopj.com/android-async-http/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值