Okhttp源码深入理解

Okhttp已经用了好几年了,一直也没去研究下它的流程是怎么样,内部究竟是怎么样工作的,最近研究了下,写篇博客记录下,写的不是很好。

首先先从用法开始。

  • 第一步:创建OkhttpClient
 val client = OkHttpClient.Builder()
  //创建Client同时可以添加拦截器、指定超时时间、证书校验等等操作
  .build()
  • 创建Request对象
//可以在这里自定请求的ip、指定请求方式。、添加请求头
  val request= Request.Builder().url("")
                .post()
                .get()
                .addHeader()
                .build()
  • 异步或者同步方式去发送请求
//同步方法
val response=client.newCall(request).execute()

//异步方法
 client.newCall(request).enqueue(object : Callback {
       override fun onFailure(call: Call, e: IOException) {

       }

        override fun onResponse(call: Call, response: Response) {

        }
  })

这样基本就完成了一次请求,下面来深入源码了解下每步的细节,

首先创建OkHttpClinet过程用到了建造者模式,添加拦截器等操作,这里没什么好说的
接着看创建Request的源码,同样也用到了建造者模式,指定请求地址、请求头什么的,也没什么好说的。
重点来了

  • 同步请求 调用client.newCall()拿到Call对象然后调用execute()方法
 /** Prepares the [request] to be executed at some point in the future. */
  override fun newCall(request: Request): Call {
    return RealCall.newRealCall(this, request, forWebSocket = false)
  }

这里看到真正干活的是RealCall这个对象 在跟进一下

   //RealCall.class
   override fun execute(): Response {
    synchronized(this) {
      check(!executed) { "Already Executed" }
      executed = true
    }
    transmitter.timeoutEnter()
    transmitter.callStart()
    try {
      client.dispatcher.executed(this)
      return getResponseWithInterceptorChain()
    } finally {
      client.dispatcher.finished(this)
    }
  }

这个方法返回Response对象,return 的是getResponseWithInterceptorChain()方法 在跟进下

  @Throws(IOException::class)
  fun getResponseWithInterceptorChain(): Response {
    // 在这里添加五大拦截器
    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(interceptors, transmitter, null, 0, originalRequest, this,
        client.connectTimeoutMillis, client.readTimeoutMillis, client.writeTimeoutMillis)

    var calledNoMoreExchanges = false
    try {
      //这里就是真正去执行网络请求的地方
      val response = chain.proceed(originalRequest)
      if (transmitter.isCanceled) {
        response.closeQuietly()
        throw IOException("Canceled")
      }
      return response
    } catch (e: IOException) {
      calledNoMoreExchanges = true
      throw transmitter.noMoreExchanges(e) as Throwable
    } finally {
      if (!calledNoMoreExchanges) {
        transmitter.noMoreExchanges(null)
      }
    }
  }

差不多到这里 整个同步请求算是完成了。同步请求看上去很简单,在梳理下流程

创建client -> 创建Request -> client.newCall(request).excute() -> RealCall.excute() -> getResponseWithInterceptorChain()
-> 拿到响应

  • 异步方法 跟同步前几步一样 我们直接来看equeue()方法
 override fun enqueue(responseCallback: Callback) {
    synchronized(this) {
      check(!executed) { "Already Executed" }
      executed = true
    }
    transmitter.callStart()
    client.dispatcher.enqueue(AsyncCall(responseCallback))
  }

判断是否已经执行 没有的话调用client.dispatcher.enqueue(AsyncCall(responseCallback)) 这里的AsyncCall是个Runable我们来看看他的run方法

   override fun run() {
      threadName("OkHttp ${redactedUrl()}") {
        var signalledCallback = false
        transmitter.timeoutEnter()
        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(INFO, "Callback failure for ${toLoggableString()}", e)
          } else {
            responseCallback.onFailure(this@RealCall, e)
          }
        } finally {
          client.dispatcher.finished(this)
        }
      }
    }

同样也去调用了getResponseWithInterceptorChain()这里就不跟进了,我们来看看 client.dispatcher.enqueue()干了些撒

 internal fun enqueue(call: AsyncCall) {
    synchronized(this) {
     //这里将异步操作放入到集合中
      readyAsyncCalls.add(call)
      ........
      promoteAndExecute()
  }

这里没撒 再来看看 promoteAndExecute()

 private fun promoteAndExecute(): Boolean {
    assert(!Thread.holdsLock(this))
    
    //可以执行的集合 应该叫队列吧
    val executableCalls = mutableListOf<AsyncCall>()
    val isRunning: Boolean
    synchronized(this) {
      val i = readyAsyncCalls.iterator()
      //不断的从集合取任务
      while (i.hasNext()) {
        val asyncCall = i.next() 
        判断是否达到了最大请求数量  maxRequests = 64
        if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
        //是否达到同时执行的最大数 maxRequestsPerHost = 5
        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
  }

我们在跟进下asyncCall.executeOn(executorService)

 //ExecutorService是线程池
  fun executeOn(executorService: ExecutorService) {
      assert(!Thread.holdsLock(client.dispatcher))
      var success = false
      try {
        //加到线程池里执行
        executorService.execute(this)
        success = true
      } catch (e: RejectedExecutionException) {
        val ioException = InterruptedIOException("executor rejected")
        ioException.initCause(e)
        transmitter.noMoreExchanges(ioException)
        responseCallback.onFailure(this@RealCall, ioException)
      } finally {
        if (!success) {
          client.dispatcher.finished(this) // This call is no longer running!
        }
      }
    }

到此异步请求过程也完了,梳理下流程
创建client -> 创建Request -> client.newCall(request).equeue(callbaclk) -> RealCall.enqueue() -> client.dispatcher.enqueue(AsyncCall)往队列里添加AsyncCall -> 判断是否到达线程池最大数量 -> 加入线程池执行 -> getResponseWithInterceptorChain() -> 以Callback形式回调回去

接下来看下拦截器的原理

拦截器在getResponseWithInterceptorChain()里添加到一个集合中,

@Throws(IOException::class)
  fun getResponseWithInterceptorChain(): Response {
   ....
     //关键1  interceptors是拦截器集合  
     val chain = RealInterceptorChain(interceptors, transmitter, null, 0, originalRequest, this,
        client.connectTimeoutMillis, client.readTimeoutMillis, client.writeTimeoutMillis)
     //关键2
      val response = chain.proceed(originalRequest)
      .....
      return response

   }

getResponseWithInterceptorChain()方法中生成一个链,看方法的名称可以猜到chain是拦截器的链
在这里插入图片描述
创建链后调用了chain.proceed(originalRequest)跟进一下这个方法

  override fun proceed(request: Request): Response {
    return proceed(request, transmitter, exchange)
  }

  @Throws(IOException::class)
  fun proceed(request: Request, transmitter: Transmitter, exchange: Exchange?): Response {
    if (index >= interceptors.size) throw AssertionError()

    calls++
   .......省略
      // Call the next interceptor in the chain.  关键
      val next = RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout)
        //index是上一个拦截器构造方法传进来的 +1就是调链的下一个
      val interceptor = interceptors[index]

    //执行一个拦截器
    @Suppress("USELESS_ELVIS")
    val response = interceptor.intercept(next) ?: throw NullPointerException(
        "interceptor $interceptor returned null")
    .......省略
    return response
  }

在这里插入图片描述
在类的方法里有new了自己 然后在interceptor.intercept(next)怎么感觉在递归呢? 是不是一下子明白了?其实就是递归,这种写法我看了好几遍才看懂 哈哈 还是不懂?再来看段代码,随便找个拦截器 ,就拿ConnectInterceptor 代码少的把

/** Opens a connection to the target server and proceeds to the next interceptor. */
object ConnectInterceptor : Interceptor {
 //假如这里的chain是 interceptor.intercept(next) 的next
  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
     ....省略
    //看这里  又去掉了proceed方法???还不懂?
    //每个拦截器都有这个方法,就算自定义拦截器最后也是要 return chain.proceed(request)
    return realChain.proceed(request, transmitter, exchange)
  }
}

还不懂吗?哈哈。不懂在好好思虑下,。我先把流程整理下
RealInterceptorChain.proceed() -> Interceptor.intercept() -> RealInterceptorChain.proceed() -> Interceptor.intercept() -> 以此类推

在执行请求前递归执行了所有的拦截器,用到责任链设计模式

五大拦截器作用 就不去深究了源码了,大概了解下
  • RetryAndFollowUpInterceptor:重试拦截器 重试机制 重定向
  • BridgeInterceptor:桥接拦截器 基础的操作,比如添加cookie、Content-type、Content-Length
  • CacheInterceptor:缓存拦截器 顾名思义做缓存的
  • ConnectInterceptor:连接的拦截器 内部封了Socket的连接池 同一个主机不断开连接
  • CallServerInterceptor(读写拦截器) 读写数据流 数据流操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值