okhttp异步请求:AsyncCall、线程池、双向队列

同步,异步请求代码前几部都是比较类似的,直接从调用异步请求开始。

通过newCall获取到call请求对象的实例,然后调用enqueue来进行异步网络请求。传入Callback这个参数加入到call当中,callback对象很好理解,就是在请求结束之后接口回调 ,请求成功用onResponse,失败调用onFailure。

看一下enqueue这个方法的实现:

call是个借口,已经很熟悉了。看一下他的实现类RealCall时怎样做的:

首先通过synchronized这个关键字锁住当前对象,这个对象就是RealCall对象。

然后对executed这个字段进行判断,用于表示这个call的实例以前有没有执行过,如果为true表示执行过了,这时候就会抛出异常"Already Executed",call请求只能执行一次,不管同步也好异步也好。

通过传进来的callback封装了AsyncCall这个对象,这个对象其实就是一个Runnable,在构建了一个Runnable,AsyncCall之后就直接调用了dispatcher().enqueue这个方法,并将前面创建好的AsyncCall传到这个方法当中。

client.dispatcher()返回的就是一个dispatcher对象,同时他的初始化操作也是在前面构建okhttpClient对象的时候他内部的构造方法已经初始化好了dispatcher默认值。


接下来看一下啊enqueue这个方法:

enqueue这个方法本身加了一个同步锁,并且这是个方法传入了刚才Runnable的实例,也就是AsyncCall对象。

首先是一个判断,就是正在运行的这个异步任务和正在调度请求每一个主机的最大数进行这两个值的判断,如果这两个值都在最大数里面,那么就可以把刚才传进来的AsyncCall这个对象添加到我们正在执行的异步请求队列当中,如果不满足就会加到准备就绪的异步请求队列当中。如果满足条件就会调用线程池的execute这个方法来进行执行。


先来看一下dispatcher中定义的几个常量和三个队列:

maxRequests代表线程最大的并发数为64;

maxRequestsPerHost表示每一个主机最大的请求书为5,也就是说超过5了就不满足刚才那个条件了。

第一个readySyncCalls队列代表的是缓存等待的请求队列

第二个runningAsyncCalls是正在执行的异步请求队列

第三个runningSyncCalls是正在运行的同步的请求队列

我们会发起一个网络请求,判断当前正在请求的runningSyncCalls的个数是否小于maxRequests(64),而且当前网络请求的Host个数是否小于5个,如果是,就会把这个请求加到我们正在请求的这个异步请求队列当中,并且通过线程池去执行相应的请求,如果不是就把他加到等待的请求队列当中。如果从等待的请求队列到正在请求的请求队列会通过disptcher进行判断,这样就完成了一次完整的网络请求。


回到前面:

就是网络请求完成以后他会回调callback的响应方法,请求成功后的结果通过response来完成的。

onFailure,onResponse都是在子线程中完成的,所以说如果你要更新Ui操作的话,需要切换到主线程。


总结一下okhttp异步网络请求:

1.生成一个OkHttpClient对象

2.创建request对象,里面包含url,网络请求信息,然后通过request对象生成call对象

3.通过Call对象的enqueue方法来进行异步网络请求,这里会创建一个call对象加入到调度当中,然后利用callback进行回调

4.不管异步同步网络请求,都是通过拦截器链来实现的,通过依次执行拦截器链子中的每一个拦截器,每一个拦截器作用都是不一样的,最终会得到服务器的数据返回。

你可能感兴趣的:(okhttp异步请求:AsyncCall、线程池、双向队列)