android-async-http解析和使用

loopj/android-async-http github地址
官网

Features

  • Make asynchronous HTTP requests, handle responses in anonymous callbacks
    发送异步http请求,在匿名callback对象中处理response信息;
  • HTTP requests happen outside the UI thread
    http请求发生在UI(主)线程之外的异步线程中;
  • Requests use a threadpool to cap concurrent resource usage
    内部采用线程池来处理并发请求;
  • GET/POST params builder (RequestParams)
    通过RequestParams类构造GET/POST,Builder方式。
  • Multipart file uploads with no additional third party libraries
    内置多部分文件上传,不需要第三方库支持;
  • Tiny size overhead to your application, only 60kb for everything
    和你的app大小相比来说,库的size很小,所有的一切只有90kb;
  • Automatic smart request retries optimized for spotty mobile connections
    在各种各样的移动连接环境中具备自动智能请求重试机制;
  • Automatic gzip response decoding support for super-fast requests
    自动的gzip响应解码
  • Optional built-in response parsing into JSON (JsonHttpResponseHandler)
    内置多种形式的响应解析,有原生的字节流,string,json对象,甚至可以将response写到文件中
  • Optional persistent cookie store, saves cookies into your app’s SharedPreferences
    cookie保存,内部实现用的是Android的SharedPreferences;

AsyncHttpClient 使用demo

1
2
3
4
5
6
7
8
9
10
11
12
13
AsyncHttpClient client = new AsyncHttpClient();
client.get("https://www.google.com", new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
System.out.println(response);
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable
error)

{

error.printStackTrace(System.out);
}
});

整体操作流程

android-async-http最简单基础的使用只需如下步骤:

1、创建一个AsyncHttpClient;

2、(可选的)通过RequestParams对象设置请求参数;

3、调用AsyncHttpClient的某个get方法,传递你需要的(成功和失败时)callback接口实现,一般都是匿名内部类,实现了AsyncHttpResponseHandler,类库自己也提供许多现成的response handler,你一般不需要自己创建。

一、先创建一个AsyncHttpClient

AsyncHttpClient client = new AsyncHttpClient();

  • 1、创建SchemeRegistry,用于定义支持哪种协议(目前只支持http/https)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    private static SchemeRegistry getDefaultSchemeRegistry(boolean fixNoHttpResponseException, int httpPort, int httpsPort) {
    //省略一系列参数判断。

    // Fix to SSL flaw in API < ICS
    // See https://code.google.com/p/android/issues/detail?id=13117
    SSLSocketFactory sslSocketFactory;
    if (fixNoHttpResponseException) {
    sslSocketFactory = MySSLSocketFactory.getFixedSocketFactory();
    } else {
    sslSocketFactory = SSLSocketFactory.getSocketFactory();
    }

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), httpPort));
    schemeRegistry.register(new Scheme("https", sslSocketFactory, httpsPort));

    return schemeRegistry;
    }
  • 2、初始化请求参数BasicHttpParams,添加Header

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    BasicHttpParams httpParams = new BasicHttpParams();

    ConnManagerParams.setTimeout(httpParams, connectTimeout);
    ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections));
    ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);

    HttpConnectionParams.setSoTimeout(httpParams, responseTimeout);
    HttpConnectionParams.setConnectionTimeout(httpParams, connectTimeout);
    HttpConnectionParams.setTcpNoDelay(httpParams, true);
    HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);

    HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
  • 3、根据schemeRegistry 和 httpParams创建连接管理 ClientConnectionManager

    1
    ClientConnectionManager cm = createConnectionManager(schemeRegistry, httpParams);
  • 4、创建线程池

    1
    threadPool = getDefaultThreadPool();
  • 5、根据cm和httpParams创建HttpClient
    Creates a new HTTP client from parameters and a connection manager.

    1
    httpClient = new DefaultHttpClient(cm, httpParams);
  • 6、调用httpClient addRequestInterceptor和addResponseInterceptor,设置请求和反馈回调.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
    @Override
    public void process(HttpRequest request, HttpContext context) { //省略
    }
    });

    httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
    @Override
    public void process(HttpResponse response, HttpContext context) {
    //省略
    }
    });

    httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
    @Override
    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
    //省略
    }
    }, 0);
  • 最后setHttpRequestRetryHandler,设置重试的Handler

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

二、通过RequestParams对象设置请求参数;

传入key-value的键值对,作为请求参数

三、请求

1
2
3
4
5
6
7
public RequestHandle get(String url, ResponseHandlerInterface responseHandler) {
return get(null, url, null, responseHandler);
}

public RequestHandle get(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) {
return sendRequest(httpClient, httpContext, new HttpGet(getUrlWithQueryString(isUrlEncodingEnabled, url, params)), null, responseHandler, context);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
protected RequestHandle sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) {

if (responseHandler.getUseSynchronousMode() && !responseHandler.getUsePoolThread()) {
throw new IllegalArgumentException("Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead.");
}

if (contentType != null) {
if (uriRequest instanceof HttpEntityEnclosingRequestBase && ((HttpEntityEnclosingRequestBase) uriRequest).getEntity() != null && uriRequest.containsHeader(HEADER_CONTENT_TYPE)) {
log.w(LOG_TAG, "Passed contentType will be ignored because HttpEntity sets content type");
} else {
uriRequest.setHeader(HEADER_CONTENT_TYPE, contentType);
}
}

responseHandler.setRequestHeaders(uriRequest.getAllHeaders());
responseHandler.setRequestURI(uriRequest.getURI());

//所有的请求处理都在这
AsyncHttpRequest request = newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context);
//启用线程池
threadPool.submit(request);
//对AsyncHttpRequest进行了WeekReference包装。
RequestHandle requestHandle = new RequestHandle(request);

if (context != null) {
List<RequestHandle> requestList;
// Add request to request map
synchronized (requestMap) {
requestList = requestMap.get(context);
if (requestList == null) {
requestList = Collections.synchronizedList(new LinkedList<RequestHandle>());
requestMap.put(context, requestList);
}
}

requestList.add(requestHandle);

Iterator<RequestHandle> iterator = requestList.iterator();
while (iterator.hasNext()) {
if (iterator.next().shouldBeGarbageCollected()) {
iterator.remove();
}
}
}

return requestHandle;
}

最后官网推荐使用Static Http Client

Recommended Usage: Make a Static Http Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import com.loopj.android.http.*;

public class TwitterRestClient {
private static final String BASE_URL = "https://api.twitter.com/1/";

private static AsyncHttpClient client = new AsyncHttpClient();

public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.get(getAbsoluteUrl(url), params, responseHandler);
}

public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.post(getAbsoluteUrl(url), params, responseHandler);
}

private static String getAbsoluteUrl(String relativeUrl) {
return BASE_URL + relativeUrl;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.json.*;
import com.loopj.android.http.*;

class TwitterRestClientUsage {
public void getPublicTimeline() throws JSONException {
TwitterRestClient.get("statuses/public_timeline.json", null, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
// If the response is JSONObject instead of expected JSONArray
}

@Override
public void onSuccess(int statusCode, Header[] headers, JSONArray timeline) {
// Pull out the first event on the public timeline
JSONObject firstEvent = timeline.get(0);
String tweetText = firstEvent.getString("text");

// Do something with the response
System.out.println(tweetText);
}
});
}
}

类图

#其他的用法见官网

  • Persistent Cookie Storage with PersistentCookieStore
  • Adding GET/POST Parameters with RequestParams
  • Uploading Files with RequestParams
  • Downloading Binary Data with FileAsyncHttpResponseHandler
  • Adding HTTP Basic Auth credentials