asynchttpclient源码分析

1. 介绍
使用Android自带httpclient编写网络请求是一件非常痛苦的事情,你需要熟知http请求首部字段、实体首部等的含义,还需要开启子线程执行相关操作然后将执行结果返回。首部字段玲琅满目和请求结果格式的不统一(json,string,字节流)是编写网络请求代码的痛点,市面上有很多的开源框架帮助我们完成了这些繁杂和重复的操作,比较常用的有:xUtil,aFinal,okHttp,volley,retrofit,android-async-http等。
各个框架原理大致相似,此篇分析android-async-http源码。个人对开源框架的态度是没有必要深抠实现细节,但是大致流程要知道,以免遇到问题不知所措。还有开源框架的模式也是值得我们去学习和模仿的。
android-async-http的项目地址在: http://loopj.com/android-async-http/

2. 源码分析
这是官方提供的使用实例

AsyncHttpClient client = new AsyncHttpClient();
client.get("https://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
    }
});
  • 请求预处理

这里的url为baseUrl,内部会把通过getUrlWithQueryString方法将url和RequestParams拼接为全连接形式的字符串,然后将该字符串作为参数创建为内部的一个HttpGet对象,并调用sendReques方法将请求组织成内部使用的一个AsyncHttpRequest对象
这里写图片描述

AsyncHttpRequest request = newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context);
        threadPool.submit(request);
        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();
                }
            }
        }

第1行:将请求组成为一个AsyncHttpRequest对象,该对象为一个Runnable对象,负责网络请求的连接,请求结果的分发、逻辑取消、重试等逻辑
第2行:将AsyncHttpRequest投递到内部的一个线程池中,自然AsyncHttpRequest内部逻辑在该线程获得cpu资源的时候执行
第3行:将AsyncHttpRequest作为参数创建为一个RequestHandle实例,该类负责请求的取消功能
第5-23行:AsyncHttpClient 内部维持了一个Map,以context为key,RequestHandle集合为值,这样就可以通过context取消该context绑定的请求和处理线程关系了。

  • 实际网络请求、重试逻辑
    这里写图片描述
    AsyncHttpRequest内部有很多的内部属性,前几个是网络请求相关api,isCancelled标示该请求是否被取消,executionCount用来记录请求执行次数从而处理重试逻辑,cancelIsNotified用来标示是否已经处理过cancel消息,isFinished标示请求是否完成(这里的完成跟请求结果成功、失败、被取消无关),isRequestPreProcessed标示在请求前的一个回调方法(该方法在子线程中执行)。
@Override
    public void run() {
        if (isCancelled()) {
            return;
        }

        // Carry out pre-processing for this request only once.
        if (!isRequestPreProcessed) {
            isRequestPreProcessed = true;
            onPreProcessRequest(this);
        }

        if (isCancelled()) {
            return;
        }

        responseHandler.sendStartMessage();

        if (isCancelled()) {
            return;
        }

        try {
            makeRequestWithRetries();
        } catch (IOException e) {
            if (!isCancelled()) {
                responseHandler.sendFailureMessage(0, null, null, e);
            } else {
                AsyncHttpClient.log.e("AsyncHttpRequest", "makeRequestWithRetries returned error", e);
            }
        }

        if (isCancelled()) {
            return;
        }

        responseHandler.sendFinishMessage();

        if (isCancelled()) {
            return;
        }

        // Carry out post-processing for this request.
        onPostProcessRequest(this);

        isFinished = true;
    }

第7-10行:处理onPreProcessRequest函数,该函数在实际网络请求前执行且只会被执行一次,目前该方法默认空置,可由子类扩展
第17行:发出开始消息,代表开始网络请求
第23-30行:发出网络请求,请求失败会发出失败消息
第37行:发出网络请求完成消息,结果可能成功也可能失败
第44行:处理onPostProcessRequest函数,与onPreProcessRequest对应,默认空置,可由子类拓展

makeRequestWithRetries函数主要是配合HttpRequestRetryHandler接口完成重试操作,实际网络请求在makeRequest中执行

 private void makeRequest() throws IOException {
        if (isCancelled()) {
            return;
        }

        // Fixes #115
        if (request.getURI().getScheme() == null) {
            // subclass of IOException so processed in the caller
            throw new MalformedURLException("No valid URI scheme was provided");
        }

        if (responseHandler instanceof RangeFileAsyncHttpResponseHandler) {
            ((RangeFileAsyncHttpResponseHandler) responseHandler).updateRequestHeaders(request);
        }

        HttpResponse response = client.execute(request, context);

        if (isCancelled()) {
            return;
        }

        // Carry out pre-processing for this response.
        responseHandler.onPreProcessResponse(responseHandler, response);

        if (isCancelled()) {
            return;
        }

        // The response is ready, handle it.
        responseHandler.sendResponseMessage(response);

        if (isCancelled()) {
            return;
        }

        // Carry out post-processing for this response.
        responseHandler.onPostProcessResponse(responseHandler, response);
    }

这样就把执行结果以及各种状态消息统统传递给了ResponseHandlerInterface,下面再来看消息的分发

  • 执行结果以及状态消息的分发
    执行结果和消息的分发操作在AsyncHttpResponseHandler类中实现的
    这里写图片描述
    是根据useSynchronousMode这个属性来判断分发操作在那个线程执行,分发操作比较简单,比较重要的是线程的选择,是在setUseSynchronousMode这一个方法中完成的。
    首先当我们创建一个AsyncHttpResponseHandler子类对象的时候,默认会通过this(null)执行该构造方法
 public AsyncHttpResponseHandler(Looper looper) {
        this.looper = looper == null ? Looper.myLooper() : looper;

        // Use asynchronous mode by default.
        setUseSynchronousMode(false);

        // Do not use the pool's thread to fire callbacks by default.
        setUsePoolThread(false);
    }

这里参数默认为空,所以会通过Looper.myLooper获取当前线程ThreadLocal存储的那个Looper然后赋值给this.looper属性,然后调用setUseSynchronousMode方法操作Handler

 public void setUseSynchronousMode(boolean sync) {
        // A looper must be prepared before setting asynchronous mode.
        if (!sync && looper == null) {
            sync = true;
            AsyncHttpClient.log.w(LOG_TAG, "Current thread has not called Looper.prepare(). Forcing synchronous mode.");
        }

        // If using asynchronous mode.
        if (!sync && handler == null) {
            // Create a handler on current thread to submit tasks
            handler = new ResponderHandler(this, looper);
        } else if (sync && handler != null) {
            // TODO: Consider adding a flag to remove all queued messages.
            handler = null;
        }

        useSynchronousMode = sync;
    }

这里会根据是否同步和Looper的有无,来创建Handler或者置handler为null,后边sendMessage方法根据handler是否为null来执行同步回调还是异步回调,然后定义了好多种不同类型的回调类供我们选择是将结果处理为json、string或者是字节流了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值