OkHttp 源码解析(Kotlin版)——拦截器

491 阅读2分钟

上一次讲到,OkHttp无论是同步请求还是异步请求,最后的结果都是返回getResponseWithInterceptorChain() ,它是RealCall类里的一个方法,实际上就是请求通过由若干个拦截器组成的拦截链返回的Response对象。

getResponseWithInterceptorChain()

@Throws(IOException::class)
internal fun getResponseWithInterceptorChain(): Response {
  // Build a full stack of interceptors.
  val interceptors = mutableListOf<Interceptor>()
  interceptors += client.interceptors
  interceptors += RetryAndFollowUpInterceptor(client)
  interceptors += BridgeInterceptor(client.cookieJar)
  interceptors += CacheInterceptor(client.cache)
  interceptors += ConnectInterceptor
  if (!forWebSocket) {
    interceptors += client.networkInterceptors
  }
  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)
    }
  }
}

image.png

建立一个完整的拦截器堆栈,由5个拦截器组成:

1.RetryAndFollowUpInterceptor(重试并重定向拦截器)

2.BridgeInterceptor(桥梁拦截器)

3.CacheInterceptor(缓存拦截器)

4.ConnectInterceptor(连接拦截器)

5.CallServerInterceptor(呼叫服务器拦截器)

image.png

将拦截器堆栈interceptors,转换成拦截链chain

image.png val response = chain.proceed(originalRequest)

我们来看proceed方法

image.png 前四个拦截器都会去调用proceed方法,加上getResponseWithInterceptorChain()调用一次,就调用了5次proceed方法,然后通过copy方法来调用下一个拦截器,其中index+1

image.png 我们发现copy方法中又new了一个RealInterceptorChain对象,可以用递归的思想来理解

image.png 最后将拦截对象传递给拦截器得到response

注意!!!

拦截器通常是先对request进行处理,再调用proceed方法,然后对response进行处理。

可以理解为以proceed方法为分割线。

这也就是我们通常说的责任链模式,依次执行拦截器1对request处理部分,然后传递给拦截器2对request处理部分,传递给最后一个拦截器即第n个,然后由第n个传回第n-1个处理response,直到传回第一个。

不仅okhttp自带有拦截器,我们也可以自行添加拦截器。我们添加的拦截器在okhttp原有拦截器之前,比如我们先添加日志拦截器1,再添加日志拦截器2,执行日志拦截器1对request处理部分,再执行日志拦截器2对request处理部分,再执行okhttp自带的拦截器,最后先传回给日志拦截器2对response处理部分,再传给日志拦截器1对response处理部分,因为日志拦截器基本都是对response进行日志打印,所以日志拦截器2的日志先打印出来。

总结

  • OkHttp 整个请求流程是由一条拦截链完成,拦截链会用递归的方式来遍历整个拦截器列表,直到最后一个拦截器才停止递归,等所有的拦截器遍历完了网络请求也就结束了,然后由拦截链返回最终的请求结果。

参考博客

www.jianshu.com/p/e0f324fd9…

下一篇:

juejin.cn/post/700656…