OkHttp的实现原理(二)之异步

上一篇我分析了OkHttp采用同步请求的实现原理,这一篇我将继续分析它的第二种请求方式——异步请求,由于这是基于上一篇文章的内容之上的,所以在看这篇文章之前请先浏览上一篇文章http://blog.csdn.net/kbqf24/article/details/56839535

所谓异步,就是我们不需要坐着等待它出结果,当它有了结果后会回调相应的方法。

让我们来看看OKHttp的异步请求是如何实现的:

public void enqueue(Callback responseCallback) {
        this.enqueue(responseCallback, false);
    }

我们要传一个Callback接口对象进去,

 void enqueue(Callback responseCallback, boolean forWebSocket) {
        synchronized(this) {
            if(this.executed) {
                throw new IllegalStateException("Already Executed");
            }

            this.executed = true;
        }

        this.client.getDispatcher().enqueue(new Call.AsyncCall(responseCallback, forWebSocket, null));
    }

首先还是要获得一个分发器,这点跟同步请求是一模一样的,接着往下看

synchronized void enqueue(AsyncCall call) {
        if(this.runningCalls.size() < this.maxRequests && this.runningCallsForHost(call) < this.maxRequestsPerHost) {
            this.runningCalls.add(call);
            this.getExecutorService().execute(call);
        } else {
            this.readyCalls.add(call);
        }

    }

原来进行异步请求是有门槛限制的,它要求总的异步请求的数量小于maxRequests =64,并且对于一个主机来说最多同时发出5个请求,如果没有满足这个条件,那么就将这个call对象加入到readyCalls数组中以备日后使用,这个数组相当于是一个缓冲数组,如果满足了这个条件,那么就将AsyncCall这个对象添加到runningCalls数组当中,并且使用线程池来执行这个任务,那么这个AsyncCall到底是什么了?它是Call的一个内部类并且实现了Runnable接口,那么走 this.getExecutorService().execute(call);这个方法当然就是要去执行call里面的run()方法啊,我们来看看这个方法:

 public final void run() {
        String oldName = Thread.currentThread().getName();
        Thread.currentThread().setName(this.name);

        try {
            this.execute();
        } finally {
            Thread.currentThread().setName(oldName);
        }

    }

这个方法会去执行execute(),并且会在执行期间给每个任务所在的线程取不同的名字。

 protected void execute() {
            boolean signalledCallback = false;

            try {
                Response e = Call.this.getResponseWithInterceptorChain(this.forWebSocket);
                if(Call.this.canceled) {
                    signalledCallback = true;
                    this.responseCallback.onFailure(Call.this.originalRequest, new IOException("Canceled"));
                } else {
                    signalledCallback = true;
                    this.responseCallback.onResponse(e);
                }
            } catch (IOException var7) {
                if(signalledCallback) {
                    Internal.logger.log(Level.INFO, "Callback failure for " + Call.this.toLoggableString(), var7);
                } else {
                    Request request = Call.this.engine == null?Call.this.originalRequest:Call.this.engine.getRequest();
                    this.responseCallback.onFailure(request, var7);
                }
            } finally {
                Call.this.client.getDispatcher().finished(this);
            }

        }
Response e = Call.this.getResponseWithInterceptorChain(this.forWebSocket);

这个方法是不是也很熟悉啊,跟同步获取数据的方法是一摸一样的,一个方法在上一篇文章中详细说明了的,这里就不再展开来说了,然后再判断这个任务是否被cancel掉了,如果是,那么就会调用我们传入的Callback接口对象的onFailure()方法,如果没有被取消,那么就会回调该接口中的onResponse(response)方法。
那么异步请求的代码我们也就分析完了,跟同步请求其实区别并不大,我们来分析一下他们的区别,
1. 同步:将Call对象之间放入分发器Dispatcher中
异步:将AsyncCall对象放入分发器Dispatcher中,
2. 同步方法不会自动给你开线程去调用getResponseWithInterceptorChain(this.forWebSocket)获取数据,所以你必须自己开启线程去执行。
异步方法OkHttp会使用内部的线程池中的线程去执行获取数据(getResponseWithInterceptorChain(this.forWebSocket))的耗时操作,所以你可以在主线程中使用异步请求。
3. 同步方法拿到返回的结果后直接返回,而异步请求获取到结果后并不直接返回,而是将结果作为参数回调接口的方法去使用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值