阅读 191

OkHttp架构解析

OkHttp架构解析

Dispatcher分发器

内部维护队列与线程池,完成请求的调配。

问题一:请求发送到哪里去?

Dispatcher是保存同步和异步Call的地方,并负责执行异步AsyncCall。

  • 针对同步请求,Dispatcher使用了一个Deque保存了同步任务;
  • 针对异步请求,Dispatcher使用了两个队列Deque,一个保存准备执行的请求(readyAsyncCalls),一个保存正在执行的请求(runningAsyncCalls)
  • 为什么要用两个呢?因为Dispatcher默认支持最大的并发请求是64个,单个Host最多执行5个并发请求,如果超过,则Call会先被放入到readyAsyncCall中,当出现空闲的线程时,再将readyAsyncCall中的线程移入到runningAsynCalls中,执行请求。

异步请求流程:

  1. 异步请求 Call (RealCall)—>enqueue()
  2. RealCall 的enqueue()
  3. dispatcher 的enqueue():将请求添加到等待执行的异步请求队列中
  4. 不断从readyAsyncCalls中取出要执行的请求放到runningAsyncCalls中,并将readyAsyncCalls中的移除,如果其中的runningAsynCalls不满,且call占用的host小于最大数量,则将call加入到runningAsyncCalls中执行
getResponseWithInterceptorChain();
复制代码

问题二:如何从ready移动到running?

每次任务结束后,都会在ready中读取一个任务放进running中。

每个请求执行完成就会从running移除,同时进行第一步相同逻辑的判断,决定是否移动。

client.dispatcher().finished(this);
复制代码

问题三:分发器的线程池是怎么定义的?

无等待,最大并发。SynchronousQueue : 无容量的队列。

  • 为什么使用线程池?

原因:由于请求数量较大,请求的生命周期较短,会导致频繁的创建和销毁请求,同时也会频繁的创建和销毁该请求对应的线程,有可能会造成内存抖动等问题,所以使用了线程池。

  • 为什么这么设计线程池?

个人理解:因为在请求发送时,分发器已经维护两个队列,这两个队列框架可以自身进行维护,如果发到线程池里还有一个队列的话,就代表着会有三个队列,在线程池还要再次等待,会导致效率低下

Interceptor拦截器

完成整个请求过程

Http请求的过程:DNS解析-->建立Tcp/Ip连接-->使用socket对象的输出流写出http的报文

文章分类
Android
文章标签