android-async-http框架源码分析详解手机开发
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程序应用开发手机开发无线开发移动端开发相关文章
- opera携全新webkit引擎登陆Android
- 74款android开机动画,修改Android系统开机动画
- android activity自动跳转,Android activity跳转之finish()方法的作用
- android 自定义控件 使用declare-styleable进行配置属性(源码角度)「建议收藏」
- Android ViewPager 垂直滑动 纵向滑动 VerticalViewPager[通俗易懂]
- android短信验证码方案,Android开发之属于你的短信验证码(一)
- android toast全屏,Android Toast实现全屏显示
- android toast显示时间,Android Toast自定义显示时间「建议收藏」
- Android渲染流程
- Android 数据库加密 android-database-sqlcipher 开源版本编译过程
- 软件分享 | 第三十六期 蓝光线路 点播直播一体TV盒子(Android、Pad、TV、BOX)
- 【Android 系统开发】Android框架 与 源码结构
- 【Android 性能优化】应用启动优化 ( Trace 文件分析 | 结合代码分析 Trace 文件 )
- 【Android 热修复】热修复原理 ( 类加载机制 | PathClassLoader 加载 Dex 机制 | PathDexList 查找 Class 机制 | 类查找的顺序机制 )
- 【Android Gradle】安卓应用构建流程 ( Java 源码编译 和 AIDL 文件编译 )
- 【IOC 控制反转】Android 事件依赖注入 ( 事件三要素 | 修饰注解的注解 | 事件依赖注入步骤 )
- 【Android 逆向】类加载器 ClassLoader ( 类加载器源码简介 | BaseDexClassLoader | DexClassLoader | PathClassLoader )
- 【Android 逆向】整体加固脱壳 ( 脱壳点简介 | 修改系统源码进行脱壳 )
- 【错误记录】Android Studio 中查看 Gradle 配置的方法源码 ( 配置 gradle-wrapper.properties 中版本为 gradle-x.x.x-all.zip )
- 【Android UI】贝塞尔曲线 ① ( 一阶贝塞尔曲线 | 二阶贝塞尔曲线 )
- 【Android UI】贝塞尔曲线 ⑥ ( 贝塞尔曲线递归算法原理 | 贝塞尔曲线递归算法实现 )
- 【Android Gradle 插件】自定义 Gradle 任务 ⑤ ( 为自定义 Gradle 任务添加依赖任务 | Gradle 任务依赖执行顺序控制 )
- Google Android MVP示例解读
- Android控制文字水平间距android:letterSpacing详解手机开发
- Android Volley网络通信框架的使用(一):Volley的简单用法详解手机开发
- Android Studio 导入项目 出现安装Error:Cause: failed to find target with hash string ‘android-23’ 等错误详解手机开发
- Android 4.4 开发代号确定:KitKat
- 使用Android实现连接MySQL数据库:实现快速数据交互与管理(android连接mysql数据库)
- Android 12 Beta 4带来了更快的搜索体验
- Android源码学习之单例模式应用及优点介绍
- Android应用开发中模拟按下HOME键的效果(实现代码)
- Android开发之登录验证实例教程