OkHttp 4.7.2 源码解析(一):请求流程

1.前言

Android 访问网络的框架从一开始的 HttpClient 和 HttpUrlConnection,再到 Volley 等,直到现在已经是 OkHttp + Retrofit 的结合。OkHttp 会成为一种流行的网络请求框架,肯定有它的特点,此篇文章将梳理 OkHttp 的源码,对于 Retrofit 将在其他后续进行分析。

OkHttp 请求网络的方式如下所示,以下将根据这个流程进行分析。

//1.创建一个 Request
        val request = Request.Builder().url(url)
            .method("GET", null)
            .build()
//2.创建一个 Client
        val okHttpClient = OkHttpClient.Builder().build()
//3.得到一个 Call
        val call = okHttpClient.newCall(request)
//4.1.异步请求
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
            }

            override fun onResponse(call: Call, response: Response) {
                val result = response.body?.string()
                if (result != null) {
                    Log.d("result", result)
                }
            }
        })

2. 构建 Request

在 Request 的 Builder 类中定义了几个参数:

open class Builder {
    internal var url: HttpUrl? = null
    internal var method: String
    internal var headers: Headers.Builder
    internal var body: RequestBody? = null

    ...

    open fun url(url: HttpUrl): Builder = apply {
      this.url = url
    }

    ...

    open fun method(method: String, body: RequestBody?): Builder = apply {
      require(method.isNotEmpty()) {
        "method.isEmpty() == true"
      }
      if (body == null) {
        require(!HttpMethod.requiresRequestBody(method)) {
          "method $method must have a request body."
        }
      } else {
        require(HttpMethod.permitsRequestBody(method)) {
          "method $method must not have a request body."
        }
      }
      this.method = method
      this.body = body
    }
    ...
}

可以看到通过调用 Builder() 的 url() 和 method() 方法是给 Builder 类中的参数进行赋值,最终返回的都是 Builder 类型,最后调用了 build() 方法去构建一个 Request 对象:

    open fun build(): Request {
      return Request(
          checkNotNull(url) { "url == null" },
          method,
          headers.build(),
          body,
          tags.toImmutableMap()
      )
    }

3. 构建 OkHttpClient

 val okHttpClient = OkHttpClient.Builder().build()

在构建 OkHttpClient 同样调用的是其内部类 Builder:

class Builder constructor() {
    internal var dispatcher: Dispatcher = Dispatcher()
    internal var connectionPool: ConnectionPool = ConnectionPool()
    internal val interceptors: MutableList = mutableListOf()
    internal val networkInterceptors: MutableList = mutableListOf()
    internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()
    internal var retryOnConnectionFailure = true
    internal var authenticator: Authenticator = Authenticator.NONE
    internal var followRedirects = true
    internal var followSslRedirects = true
    internal var cookieJar: CookieJar = CookieJar.NO_COOKIES
    internal var cache: Cache? = null
    internal var dns: Dns = Dns.SYSTEM
    internal var proxy: Proxy? = null
    internal var proxySelector: ProxySelector? = null
    internal var proxyAuthenticator: Authenticator = Authenticator.NONE
    internal var socketFactory: SocketFactory = SocketFactory.getDefault()
    internal var sslSocketFactoryOrNull: SSLSocketFactory? = null
    internal var x509TrustManagerOrNull: X509TrustManager? = null
    internal var connectionSpecs: List = DEFAULT_CONNECTION_SPECS
    internal var protocols: List = DEFAULT_PROTOCOLS
    internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier
    internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT
    internal var certificateChainCleaner: CertificateChainCleaner? = null
    internal var callTimeout = 0
    internal var connectTimeout = 10_000
    internal var readTimeout = 10_000
    internal var writeTimeout = 10_000
    internal var pingInterval = 0
    internal var minWebSocketMessageToCompress = RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE
    internal var routeDatabase: RouteDatabase? = null

    ...

    internal constructor(okHttpClient: OkHttpClient) : this() {
      this.dispatcher = okHttpClient.dispatcher
      this.connectionPool = okHttpClient.connectionPool
      this.interceptors += okHttpClient.interceptors
      this.networkInterceptors += okHttpClient.networkInterceptors
      this.eventListenerFactory = okHttpClient.eventListenerFactory
      this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure
      this.authenticator = okHttpClient.authenticator
      this.followRedirects = okHttpClient.followRedirects
      this.followSslRedirects = okHttpClient.followSslRedirects
      this.cookieJar = okHttpClient.cookieJar
      this.cache = okHttpClient.cache
      this.dns = okHttpClient.dns
      this.proxy = okHttpClient.proxy
      this.proxySelector = okHttpClient.proxySelector
      this.proxyAuthenticator = okHttpClient.proxyAuthenticator
      this.socketFactory = okHttpClient.socketFactory
      this.sslSocketFactoryOrNull = okHttpClient.sslSocketFactoryOrNull
      this.x509TrustManagerOrNull = okHttpClient.x509TrustManager
      this.connectionSpecs = okHttpClient.connectionSpecs
      this.protocols = okHttpClient.protocols
      this.hostnameVerifier = okHttpClient.hostnameVerifier
      this.certificatePinner = okHttpClient.certificatePinner
      this.certificateChainCleaner = okHttpClient.certificateChainCleaner
      this.callTimeout = okHttpClient.callTimeoutMillis
      this.connectTimeout = okHttpClient.connectTimeoutMillis
      this.readTimeout = okHttpClient.readTimeoutMillis
      this.writeTimeout = okHttpClient.writeTimeoutMillis
      this.pingInterval = okHttpClient.pingIntervalMillis
      this.minWebSocketMessageToCompress = okHttpClient.minWebSocketMessageToCompress
      this.routeDatabase = okHttpClient.routeDatabase
    }
}

 在 OkHttp 的内部类 Builder 中对相关变量进行初始化。接着调用了 build() 方法:

fun build(): OkHttpClient = OkHttpClient(this)

在 build() 方法中构建了 OkHttp 变量。

4. 构建 Call

val call = okHttpClient.newCall(request)

 通过调用 okHttpClient 的 newCall(request) 方法:

 override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)

 Call 是一个接口:

interface Call : Cloneable {
  /** Returns the original request that initiated this call. */
  fun request(): Request

  @Throws(IOException::class)
  fun execute(): Response

  fun enqueue(responseCallback: Callback)

  fun cancel()

  fun isExecuted(): Boolean

  fun isCanceled(): Boolean

  fun timeout(): Timeout

  public override fun clone(): Call

  interface Factory {
    fun newCall(request: Request): Call
  }
}

 而它的实现类是 RealCall 

class RealCall(
  val client: OkHttpClient,
  /** The application's original request unadulterated by redirects or auth headers. */
  val originalRequest: Request,
  val forWebSocket: Boolean
) : Call {

...

}

RealCall 请求方式分为两种:同步请求(execute) 和 异步请求(enqueue)。

5. 异步请求(enqueue)

调用了 RealCall 的 enqueue 方法进行异步请求:

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

 这里的核心是最后一句代码的执行,先看括号中创建的 AsyncCall(responseCallback):

  internal inner class AsyncCall(
    private val responseCallback: Callback
  ) : Runnable {
    ...
  }

AsyncCall 继承 Runnable,这里暂时不分析 AsyncCall 如何执行。先继续看 client.dispatcher.enqueue() 方法。

6.Dispatcher

Dispatcher 是在 OkHttpClient 的内部类 Builder 中进行初始化。在 Dispatcher 中定义了默认最大请求数和每个主机最大请求数:

var maxRequests = 64 // 最大请求数
var maxRequestsPerHost = 5 // 每个主机最大请求数

以及两个队列,将要执行的队列、正在执行的异步队列和正在执行的同步队列:

  /** Ready async calls in the order they'll be run. */
  private val readyAsyncCalls = ArrayDeque()

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private val runningAsyncCalls = ArrayDeque()

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private val runningSyncCalls = ArrayDeque()

接着调用了 Dispatcher 的 enqueue() 方法:

class Dispatcher constructor() {

    ...

  internal fun enqueue(call: AsyncCall) {
    synchronized(this) {
      readyAsyncCalls.add(call)
      if (!call.call.forWebSocket) {
        val existingCall = findExistingCallWithHost(call.host)
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
      }
    }
    promoteAndExecute()
  }

    ...
}

将 AsyncCall 类型的 call 添加进将要执行的队列中,接着看 promoteAndExecute() 方法:

  private fun promoteAndExecute(): Boolean {
    this.assertThreadDoesntHoldLock()

    val executableCalls = mutableListOf()
    val isRunning: Boolean
    synchronized(this) {
      val i = readyAsyncCalls.iterator()
      while (i.hasNext()) {
        val asyncCall = i.next()

        if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
        if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.

        i.remove()
        asyncCall.callsPerHost.incrementAndGet()
        executableCalls.add(asyncCall)
        runningAsyncCalls.add(asyncCall)
      }
      isRunning = runningCallsCount() > 0
    }

    for (i in 0 until executableCalls.size) {
      val asyncCall = executableCalls[i]
      asyncCall.executeOn(executorService)
    }

    return isRunning
  }

定义一个可执行的列表 executableCalls ,通过遍历将要执行的队列,并将其添加进去可执行的列表和运行中的队列中。接着遍历可执行的列表,并执行 asyncCall.executeOn(executorService) 方法,executorService 是一个线程池。

7. AsyncCall

AsyncCall 是 RealCall 的一个内部类,并且继承 Runnable:

  internal inner class AsyncCall(
    private val responseCallback: Callback
  ) : Runnable {
    ...
}

在上一步中调用了 executeOn(executorService) 方法,并将线程池传递进 AsyncCall 中:

    fun executeOn(executorService: ExecutorService) {
      client.dispatcher.assertThreadDoesntHoldLock()

      var success = false
      try {
        executorService.execute(this)
        success = true
      } catch (e: RejectedExecutionException) {
        val ioException = InterruptedIOException("executor rejected")
        ioException.initCause(e)
        noMoreExchanges(ioException)
        responseCallback.onFailure(this@RealCall, ioException)
      } finally {
        if (!success) {
          client.dispatcher.finished(this) // This call is no longer running!
        }
      }
    }

通过调用 executorService.execute(this) 执行线程,这里会执行到 AsyncCall 的 run 方法,如果出现异常,调到 catch方法中,则调用 responseCallback.onFailure,最后,执行失败,则调用 Dispatch 的 finish() 方法。

先看 run 方法:

    override fun run() {
      threadName("OkHttp ${redactedUrl()}") {
        var signalledCallback = false
        timeout.enter()
        try {
          val response = getResponseWithInterceptorChain()
          signalledCallback = true
          responseCallback.onResponse(this@RealCall, response)
        } catch (e: IOException) {
          if (signalledCallback) {
            // Do not signal the callback twice!
            Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
          } else {
            responseCallback.onFailure(this@RealCall, e)
          }
        } catch (t: Throwable) {
          cancel()
          if (!signalledCallback) {
            val canceledException = IOException("canceled due to $t")
            canceledException.addSuppressed(t)
            responseCallback.onFailure(this@RealCall, canceledException)
          }
          throw t
        } finally {
          client.dispatcher.finished(this)
        }
      }
    }

在 run 方法中的核心是以下代码,最终执行完毕都会调用 Dispatch 的 finish() 方法:

          val response = getResponseWithInterceptorChain()
          signalledCallback = true
          responseCallback.onResponse(this@RealCall, response)

 通过 getResponseWithInterceptorChain() 方法获取返回响应,并通过回调调用了 onResponse() 方法,将返回响应传递出去。

getResponseWithInterceptorChain 方法:

  @Throws(IOException::class)
  internal fun getResponseWithInterceptorChain(): Response {
    // Build a full stack of interceptors.
    val interceptors = mutableListOf()
    interceptors += client.interceptors //添加自定义的拦截器,自定义拦截器会被优先处理
    interceptors += RetryAndFollowUpInterceptor(client) //添加重试和重定向拦截器
    interceptors += BridgeInterceptor(client.cookieJar) //添加转换桥拦截器
    interceptors += CacheInterceptor(client.cache) //添加缓存拦截器
    interceptors += ConnectInterceptor //添加链接拦截器
    if (!forWebSocket) { 
      interceptors += client.networkInterceptors //不是websocket添加网络拦截器
    }
    interceptors += CallServerInterceptor(forWebSocket) //添加读取响应拦截器

    val chain = RealInterceptorChain( //得到拦截器链
        call = this,
        interceptors = interceptors,
        index = 0,
        exchange = null,
        request = originalRequest,
        connectTimeoutMillis = client.connectTimeoutMillis,
        readTimeoutMillis = client.readTimeoutMillis,
        writeTimeoutMillis = client.writeTimeoutMillis
    )

    var calledNoMoreExchanges = false
    try {
      val response = chain.proceed(originalRequest) //链式调用,任务处理
      if (isCanceled()) {
        response.closeQuietly()
        throw IOException("Canceled")
      }
      return response
    } catch (e: IOException) {
      calledNoMoreExchanges = true
      throw noMoreExchanges(e) as Throwable
    } finally {
      if (!calledNoMoreExchanges) {
        noMoreExchanges(null)
      }
    }
  }

此方法中添加一系列的拦截器,并构建拦截器链,并执行 proceed() 方法得到返回响应。

8. 拦截器 Interceptor

Interceptor 是一个接口,默认存在五种类型的拦截器,它们都是 Interceptor 的实现类:

RetryAndFollowUpInterceptor: 负责失败重试以及重定向的拦截器;
BridgeInterceptor: 负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转为用户友好的响应的;
CacheInterceptor: 负责读取缓存直接返回、更新缓存;
ConnectInterceptor: 负责和服务器建立连接的;
CallServerInterceptor:负责向服务器发送请求数据、从服务器读取响应数据;

构建拦截器链的类为 RealInterceptorChain,RealInterceptorChain 的父类是 Interceptor.chain:

  interface Chain {
    fun request(): Request

    @Throws(IOException::class)
    fun proceed(request: Request): Response

    /**
     * Returns the connection the request will be executed on. This is only available in the chains
     * of network interceptors; for application interceptors this is always null.
     */
    fun connection(): Connection?

    fun call(): Call

    fun connectTimeoutMillis(): Int

    fun withConnectTimeout(timeout: Int, unit: TimeUnit): Chain

    fun readTimeoutMillis(): Int

    fun withReadTimeout(timeout: Int, unit: TimeUnit): Chain

    fun writeTimeoutMillis(): Int

    fun withWriteTimeout(timeout: Int, unit: TimeUnit): Chain
  }

RealInterceptorChain 类:

class RealInterceptorChain(
  internal val call: RealCall,
  private val interceptors: List,
  private val index: Int,
  internal val exchange: Exchange?,
  internal val request: Request,
  internal val connectTimeoutMillis: Int,
  internal val readTimeoutMillis: Int,
  internal val writeTimeoutMillis: Int
) : Interceptor.Chain {
    ...
}

 在上面的流程中执行了 proceed() 方法:

  @Throws(IOException::class)
  override fun proceed(request: Request): Response {
    ...

    // Call the next interceptor in the chain.
    val next = copy(index = index + 1, request = request)
    val interceptor = interceptors[index]

    @Suppress("USELESS_ELVIS")
    val response = interceptor.intercept(next) ?: throw NullPointerException(
        "interceptor $interceptor returned null")
    ...

    return response
  }

 OkHttp 就是通过定义许多拦截器一步一步地对 Request 进行拦截处理(从头至尾),直到请求返回网络数据,后面又倒过来,一步一步地对 Response 进行拦截处理,最后拦截的结果就是回调的最终 Response。

9. 总结

通过 Request 的内部类 Builder 定义相关变量,并通过 url() 等方法对相关变量进行赋值,通过 build() 方法构建 Request 对象。在 OkHttpClient 的内部类 Builder 中对相关变量进行初始化,在 build() 方法中构建了 OkHttpClient 变量。 通过调用 okHttpClient 的 newCall(request) 方法,将 request 作为参数传递进去,创建一个 Call 对象。Call 是一个接口,它的实现类是 RealCall。RealCall 是对请求的封装,调用了 RealCall 的 enqueue 方法进行异步请求。Dispatcher 是在 OkHttpClient 的内部类 Builder 中进行初始化,在 Dispatcher 中定义了最大请求数为 64 和每个主机最大请求数 5。以及定义了三个队列,用于存储准备执行任务的队列、用于存储正在执行异步任务的队列和用于存储正在执行的同步任务的队列。AsyncCall 是一个 Runnable,调用了 executeOn(executorService),将线程池传递进去。executeOn 方法中通过线程池启动线程,执行 run 方法。run 方法中添加一系列的拦截器,得到拦截器链,并调用了process 方法,通过定义许多拦截器一步一步地对 Request 进行拦截处理(从头至尾),直到请求返回网络数据,后面又倒过来,一步一步地对 Response 进行拦截处理,最后拦截的结果就是回调的最终 Response。

你可能感兴趣的:(Android)