zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

android-async-http框架源码分析详解手机开发

2023-06-13 09:20:14 时间

async-http使用地址

android-async-http仓库:git clone https://github.com/loopj/android-async-http

源码分析

我们在做网络请求的时候经常通过下面的方式实例化AsyncHttpClient client=new AsyncHttpClient();然后通过系统内置的请求发送请求,通过async内部的请求去做真正的网络请求。

首先得到的是AsyncHttpClient实例,所以从这里入手分析一下:

 code style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: Source Code Pro, monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;" span /** 

 * Creates a new AsyncHttpClient with default constructor arguments values 

 span public span AsyncHttpClient() { 

 span this( span false, span 80, span 443); 

 } /code ul li 1 /li li 2 /li li 3 /li li 4 /li li 5 /li li 6 /li /ul 

对于默认值设置了HTTP协议的默认端口为80,HTTPS协议的默认端口为443。

在该函数中调用了AsyncHttpClient(SchemeRegistry schemeRegistry)构造函数,而真正的实例化获取逻辑过程就在AsyncHttpClient(SchemeRegistry schemeRegistry)方法中,如下所示:

 code style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: Source Code Pro, monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;" span /** 

 * Creates a new AsyncHttpClient. 

 * span @param schemeRegistry SchemeRegistry to be used 

 span public span AsyncHttpClient(SchemeRegistry schemeRegistry) { 

 BasicHttpParams httpParams = span new BasicHttpParams(); 

 ConnManagerParams.setTimeout(httpParams, connectTimeout); 

 ConnManagerParams.setMaxConnectionsPerRoute(httpParams, span new ConnPerRouteBean(maxConnections)); 

 ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS); 

 HttpConnectionParams.setSoTimeout(httpParams, responseTimeout); 

 HttpConnectionParams.setConnectionTimeout(httpParams, connectTimeout); 

 HttpConnectionParams.setTcpNoDelay(httpParams, span true); 

 HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE); 

 HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); 

 ClientConnectionManager cm = createConnectionManager(schemeRegistry, httpParams); 

 Utils.asserts(cm != span null, span "Custom implementation of #createConnectionManager(SchemeRegistry, BasicHttpParams) returned null"); 

 threadPool = getDefaultThreadPool(); 

 requestMap = Collections.synchronizedMap( span new WeakHashMap Context, List RequestHandle ()); 

 clientHeaderMap = span new HashMap String, String 

 httpContext = span new SyncBasicHttpContext( span new BasicHttpContext()); 

 httpClient = span new DefaultHttpClient(cm, httpParams); 

 httpClient.addRequestInterceptor( span new HttpRequestInterceptor() { 

 span @Override 

 span public span void span process(HttpRequest request, HttpContext context) { 

 span if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) { 

 request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP); 

 span for (String header : clientHeaderMap.keySet()) { 

 span if (request.containsHeader(header)) { 

 Header overwritten = request.getFirstHeader(header); 

 Log.d(LOG_TAG, 

 String.format( span "Headers were overwritten! (%s | %s) overwrites (%s | %s)", 

 header, clientHeaderMap.get(header), 

 overwritten.getName(), overwritten.getValue()) 

 span //remove the overwritten header 

 request.removeHeader(overwritten); 

 request.addHeader(header, clientHeaderMap.get(header)); 

 }); 

 httpClient.addResponseInterceptor( span new HttpResponseInterceptor() { 

 span @Override 

 span public span void span process(HttpResponse response, HttpContext context) { 

 span final HttpEntity entity = response.getEntity(); 

 span if (entity == span null) { 

 span return; 

 span final Header encoding = entity.getContentEncoding(); 

 span if (encoding != span null) { 

 span for (HeaderElement element : encoding.getElements()) { 

 span if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) { 

 response.setEntity( span new InflatingEntity(entity)); 

 span break; 

 }); 

 httpClient.addRequestInterceptor( span new HttpRequestInterceptor() { 

 span @Override 

 span public span void span process( span final HttpRequest request, span final HttpContext context) span throws HttpException, IOException { 

 AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); 

 CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute( 

 ClientContext.CREDS_PROVIDER); 

 HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST); 

 span if (authState.getAuthScheme() == span null) { 

 AuthScope authScope = span new AuthScope(targetHost.getHostName(), targetHost.getPort()); 

 Credentials creds = credsProvider.getCredentials(authScope); 

 span if (creds != span null) { 

 authState.setAuthScheme( span new BasicScheme()); 

 authState.setCredentials(creds); 

 }, span 

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

} /code ul li 1 /li li 2 /li li 3 /li li 4 /li li 5 /li li 6 /li li 7 /li li 8 /li li 9 /li li 10 /li li 11 /li li 12 /li li 13 /li li 14 /li li 15 /li li 16 /li li 17 /li li 18 /li li 19 /li li 20 /li li 21 /li li 22 /li li 23 /li li 24 /li li 25 /li li 26 /li li 27 /li li 28 /li li 29 /li li 30 /li li 31 /li li 32 /li li 33 /li li 34 /li li 35 /li li 36 /li li 37 /li li 38 /li li 39 /li li 40 /li li 41 /li li 42 /li li 43 /li li 44 /li li 45 /li li 46 /li li 47 /li li 48 /li li 49 /li li 50 /li li 51 /li li 52 /li li 53 /li li 54 /li li 55 /li li 56 /li li 57 /li li 58 /li li 59 /li li 60 /li li 61 /li li 62 /li li 63 /li li 64 /li li 65 /li li 66 /li li 67 /li li 68 /li li 69 /li li 70 /li li 71 /li li 72 /li li 73 /li li 74 /li li 75 /li li 76 /li li 77 /li li 78 /li li 79 /li li 80 /li li 81 /li li 82 /li li 83 /li li 84 /li li 85 /li li 86 /li li 87 /li li 88 /li li 89 /li li 90 /li li 91 /li li 92 /li /ul 

从代码的最顶层分析,构造参数传入的是SchemeRegistry对象,查看源码这是一个静态的方法,主要存储一些协议的东西

 public SchemeRegistry() {
        super();
        registeredSchemes = new ConcurrentHashMap String,Scheme
    }

上面的代码我们主要关注下addResponseInterceptor和addResponseInterceptor,此两个方法主要将我们的请求头和请求的实体加到HttpRequest队列中,对android1.5之前的熟悉的朋友都知道,在最早之前没有流行这些第三方之前我们就是通过HttpRequest来请求的,这等同于j2ee的HttpServletRequest.

接下来我们调运的就是AsyncHttpClient里面的各种get、post、delete等方法,通过看代码可以发现它们最终调用的都是sendRequest方法,如下:

 code style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: Source Code Pro, monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;" span /** 

 * Puts a new request in queue as a new thread in pool to be executed 

 * span @param client HttpClient to be used for request, can differ in single requests 

 * span @param contentType MIME body type, for POST and PUT requests, may be null 

 * span @param context Context of Android application, to hold the reference of request 

 * span @param httpContext HttpContext in which the request will be executed 

 * span @param responseHandler ResponseHandler or its subclass to put the response into 

 * span @param uriRequest instance of HttpUriRequest, which means it must be of HttpDelete, 

 * HttpPost, HttpGet, HttpPut, etc. 

 * span @return RequestHandle of future request process 

 span protected RequestHandle span sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) { 

 span if (uriRequest == span null) { 

 span throw span new IllegalArgumentException( span "HttpUriRequest must not be null"); 

 span if (responseHandler == span null) { 

 span throw span new IllegalArgumentException( span "ResponseHandler must not be null"); 

 span if (responseHandler.getUseSynchronousMode() !responseHandler.getUsePoolThread()) { 

 span throw span new IllegalArgumentException( span "Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead."); 

 span if (contentType != span null) { 

 span if (uriRequest span instanceof HttpEntityEnclosingRequestBase ((HttpEntityEnclosingRequestBase) uriRequest).getEntity() != span null) { 

 Log.w(LOG_TAG, span "Passed contentType will be ignored because HttpEntity sets content type"); 

 } span 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); 

 RequestHandle requestHandle = span new RequestHandle(request); 

 span if (context != span null) { 

 span // Add request to request map 

 List RequestHandle requestList = requestMap.get(context); 

 span synchronized (requestMap) { 

 span if (requestList == span null) { 

 requestList = Collections.synchronizedList( span new LinkedList RequestHandle 

 requestMap.put(context, requestList); 

 requestList.add(requestHandle); 

 Iterator RequestHandle iterator = requestList.iterator(); 

 span while (iterator.hasNext()) { 

 span if (iterator.next().shouldBeGarbageCollected()) { 

 iterator.remove(); 

 span return requestHandle; 

 } /code ul li 1 /li li 2 /li li 3 /li li 4 /li li 5 /li li 6 /li li 7 /li li 8 /li li 9 /li li 10 /li li 11 /li li 12 /li li 13 /li li 14 /li li 15 /li li 16 /li li 17 /li li 18 /li li 19 /li li 20 /li li 21 /li li 22 /li li 23 /li li 24 /li li 25 /li li 26 /li li 27 /li li 28 /li li 29 /li li 30 /li li 31 /li li 32 /li li 33 /li li 34 /li li 35 /li li 36 /li li 37 /li li 38 /li li 39 /li li 40 /li li 41 /li li 42 /li li 43 /li li 44 /li li 45 /li li 46 /li li 47 /li li 48 /li li 49 /li li 50 /li li 51 /li li 52 /li li 53 /li li 54 /li li 55 /li li 56 /li li 57 /li li 58 /li li 59 /li li 60 /li li 61 /li li 62 /li /ul 

这个方法的主要作用是将一个新的请求添加到队列线程池中执行。 

调用本方法,主要实现
AsyncHttpRequest request = newAsyncHttpRequest(client, httpContext, uriRequest,contentType, responseHandler, context);
这行开始是主要的逻辑,其创建了请求,接着通过
threadPool.submit(request);
把请求提交到线程池,接着通过
RequestHandle requestHandle = new RequestHandle(request);
把请求包装到RequestHandle用于之后的取消、管理等操作。然后坐等现在池的我们请求的这个线程去执行,等待返回结果。

总结一下:

AsyncHttpClient 核心类,使用HttpClient执行网络请求,提供了get,put,post,delete,head等请求方法,使用起来很简单,只需以url及RequestParams调用相应的方法即可,还可以选择性地传入Context,用于取消Content相关的请求,同时必须提供ResponseHandlerInterface(AsyncHttpResponseHandler继承自ResponseHandlerInterface)的实现类,一般为AsyncHttpResponseHandler的子类,AsyncHttpClient内部有一个线程池,当使用AsyncHttpClient执行网络请求时,最终都会调用sendRequest方法,在这个方法内部将请求参数封装成AsyncHttpRequest(继承自Runnable)交由内部的线程池执行。

SyncHttpClient 继承自AsyncHttpClient,同步执行网络请求,AsyncHttpClient把请求封装成AsyncHttpRequest后提交至线程池,SyncHttpClient把请求封装成AsyncHttpRequest后直接调用它的run方法。

AsyncHttpRequest 继承自Runnabler,被submit至线程池执行网络请求并发送start,success等消息。

AsyncHttpResponseHandler 接收请求结果,一般重写onSuccess及onFailure接收请求成功或失败的消息,还有onStart,onFinish等消息。

TextHttpResponseHandler、JsonHttpResponseHandler、BaseJsonHttpResponseHandler这些类都继承自AsyncHttpResponseHandler,只是重写了AsyncHttpResponseHandler的onSuccess和onFailure方法,将请求结果进行了转换而已。

RequestParams 请求参数,可以添加普通的字符串参数,并可添加File,InputStream上传文件。




5843.html

app程序应用开发手机开发无线开发移动端开发