OkHttp

Version 4.4.0

OkHttpClient 创建

可以通过建造者模式进行参数设定,会初始化调度器Dispatcher。

请求创建

请求的创建等都使用了建造者模式。

异步请求

请求真正的执行时RealCall类,同步请求使用execute,异步请求使用enqueue。

Realcall#enqueue 调用了 client.dispatcher#enqueue(AsyncCall)

// RealCall#enqueue
override fun enqueue(responseCallback: Callback) {
    synchronized(this) {
      check(!executed) { "Already Executed" }
      executed = true
    }
    callStart()
    client.dispatcher.enqueue(AsyncCall(responseCallback))
  }

先加入到等待队列中,然后通过 promoteAndExecute 方法,将等待队列中可以执行的请求添加到可执行列表中(需要满足限制条件:并发请求数量、相同host并发请求数量、线程数等等),同时添加到执行中列表中,然后通过线程池执行。

AsyncCall#run

执行请求的方法 RealCall#getResponseWithInterceptorChain(),这个方法中会将用户自定义的拦截器加上已经按职责分离的所有必须拦截器构造一个RealInterceptorChain,然后调用它的proceed 方法处理请求。

RealCall#getResponseWithInterceptorChain

请求处理使用了连接器链完成-责任链模式。

RealInterceptorChain#proceed

intercept 方法参数为 RealInterceptorChain ,该方法中需要执行 chain.proceed 进行传递。

如果要在响应前执行操作,那么可以放在 chain.proceed 之前;如果要在收到响应后再处理,可以先调用 chain.proceed 获取响应,然后再操作.

请求完成后通过 dispatcher.finish方法,将执行完的call移除队列,并在符合条件的情况下执行等待队列中的请求并添加到运行中队列。

同步请求

dispatcher 只是将 call 添加到了运行中队列:

Dispatcher

Dispatcher 有三个队列

线程池创建

默认情况下创建的线程池,核心线程数是0(没有常驻线程)、存活时间60秒。默认拒绝策略是抛异常。

请求发送

BridgeInterceptor

主要是将用户创建的请求调整为HTTP 协议格式,并将原始响应组成成Response。

CallServerInterceptor

真正用于发送请求的拦截器,这也是拦截器列表里最后一个拦截器。

主要借助Exchange来发送请求和读取响应,而 Exchange 又借助 ExchangeCodec 编解码器来进行处理。ExchangeCodec 是一个接口,实现类有 Http1ExchangeCodec 和Http2ExchangeCodec,分别对应HTTP 1.1 和 HTTP 2。

连接的初始化在 ConnectInterceptor 中进行,调用了call.initExchange 方法

RealInterceptorChain#initExchange

ExchangeFinder#find

RealConnection#newCodec

缓存处理

默认的缓存逻辑在 CacheInterceptor 中,使用DiskLruCache。

主要逻辑:

  1. 校验缓存是否可用

  2. 网络不可用、缓存不可用,返回空响应

  3. 网络不可用、缓存可用,返回缓存的响应

  4. 网络可用、发送请求,如果304,返回缓存可用,

  5. 根据最新的响应更新或添加缓存

相关链接

Github

彻底理解OkHttp - OkHttp 源码解析及OkHttp的设计思想

OkHttp必须弄清楚的几个原理性问题

最后更新于

这有帮助吗?