OkHttp分发器源码解析

OkHttp可以说是Android开发中使用最广泛的网络框架,从Android4.4开始HttpURLConnection的底层实现也被谷歌替换成OkHttp

下面先来看看okhttp同步请求的简单使用

我们可以看到,okhttp请求中最少只需要接触到OkHttpClient,Request,Call,Response,剩下的都交由框架内部进行处理。

 

 所有的逻辑大都集中在拦截器中,但在进入拦截器之前还需要依靠分发器来调配请求任务。

其中,分发器负责内部维护队列与线程池,完成请求调配,也就是说管理请求任务什么时候被执行,拦截器负责完成整个请求过程。

咱们先来看跟Dispatcher有关的源码,通过异步请求调用call身上的enqueue方法。

 

可以看到,首先调用了一个内置锁,锁的对象是当前RealCall的实例,锁内部显然是一个限制,限制获取到的call,如果对它进行了一次enqueue方法的调用,在进行一次调用时会抛出异常,所以说,call只能使用一次,如果需要再次使用,则需要调用call.clone()方法。

继续往下看,eventListener是一个监听,可以对请求开始,结束等状态进行监听。

最后一行中client,是指OkHttpClient,dispatcher()获得的是client身上的分发器,调用上面的enqueue方法,并传入一个AsyncCall,AsyncCall可以看成当前的请求任务。那接下来我们进入分发起的代码。

首先我们看一下分发其中有哪些成员。

我们可以看到,类中有三个队列,

runningAsyncCalls,正在执行的异步请求队列
readyAsyncCalls,等待执行的异步请求队列
runningSyncCalls,正在执行的同步请求队列

我们可以想到当意不请求任务进入到enqueue方法中后,会被放入runningAsyncCalls或readyAsyncCalls,那么如何决定放入哪个队列呢?read队列中的任务什么时候才能进入running队列呢?我们继续来看源码

可以看到,正在执行的异步请求个数小于maxRequest, maxRequest默认为64,防止创建过多的线程池。再看下一个条件,

 这是判断访问的域名是否相同,访问相同域名的数量不大于maxRequestsPerHost,默认为5。

那么,我们的异步请求放入running队列的条件就是 ;

1.正在执行的异步请求个数小于64.

2.与这次访问相同域名的请求个数不大于5.

之后会调用线程池,将当前任务交给线程池。我们再看回AsyncCall,AsyncCall最终集成于Runnable,Runnable的run方法中执行了一个execute的抽象方法。

 

 所以,线程池会调用线程中的execute方法。

execute上来就跑了拦截器,然后就得到了response,这里也可以看出,拦截器里处理了整个请求的发送与接收,拦截器咱们下一篇再说,先继续看源码,不管这个请求成功与否,都会执行finally中的分发器的finished方法,跳到finished中

 

 

既然完成了请求,首先把当前call从running队列中remove掉,之后如果promoreCalls为true,执行了 promoreCalls方法

 promoreCalls就是尝试将ready队列中的成员放入running队列中,只要满足与这次访问相同域名的请求个数不大于5,就可以加入running队列,如果大于5,那就走next方法判断下一个。这样循环往复就是分发器的功能。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值