OkHttp源码流程分析

2021-11-24 14:24:02 浏览数 (1)

请求方式

代码语言:txt复制
fun load() {
代码语言:txt复制
      //1.创建请求(包含url,method,headers,body)
代码语言:txt复制
      val request = Request
代码语言:txt复制
              .Builder()
代码语言:txt复制
              .url("")
代码语言:txt复制
              .build()
代码语言:txt复制
       //2.创建OkHttpClient (包含分发器、拦截器、DNS等)
代码语言:txt复制
       val okHttpClient = OkHttpClient.Builder().build()
代码语言:txt复制
       //3.创建Call(用于调用请求)
代码语言:txt复制
       val newCall = okHttpClient.newCall(request)
代码语言:txt复制
       //4.通过异步请求数据
代码语言:txt复制
       newCall.enqueue(object :Callback{
代码语言:txt复制
           override fun onFailure(call: Call, e: IOException) {}
代码语言:txt复制
           override fun onResponse(call: Call, response: Response) {}
代码语言:txt复制
       })
代码语言:txt复制
       //4.通过同步请求数据
代码语言:txt复制
       val response =  newCall.execute()
代码语言:txt复制
}

我们会按照顺序来分析一下请求的流程

前面1,2,3步很多文章已经分析过很多遍了 也比较简单 同学们可以自己看一下 我们就不再赘述 我们直接看第四步进入今天的主要流程

Okhttp请求分为同步方式和异步方式 不过最终都是殊途同归 我们以异步的方式分析一下请求流程

enqueue()

话不多说 先看一眼代码

代码语言:txt复制
RealCall.enqueue()->
代码语言:txt复制
Dispatcher.enqueue()->
代码语言:txt复制
Dispatcher.promoteAndExecute()->
代码语言:txt复制
RealCall.executeOn()
代码语言:txt复制
override fun enqueue(responseCallback: Callback) {
代码语言:txt复制
    synchronized(this) {
代码语言:txt复制
        //检查是否已经开始运行
代码语言:txt复制
      check(!executed) { "Already Executed" }
代码语言:txt复制
      executed = true
代码语言:txt复制
    }
代码语言:txt复制
    callStart()
代码语言:txt复制
    //封装AsyncCall对象 并放入队列中等待执行
代码语言:txt复制
    client.dispatcher.enqueue(AsyncCall(responseCallback))
代码语言:txt复制
  }
代码语言:txt复制
internal fun enqueue(call: AsyncCall) {
代码语言:txt复制
    synchronized(this) {
代码语言:txt复制
        //放入等待队列
代码语言:txt复制
      readyAsyncCalls.add(call)
代码语言:txt复制
      // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
代码语言:txt复制
      // the same host.
代码语言:txt复制
      if (!call.call.forWebSocket) {
代码语言:txt复制
        val existingCall = findExistingCallWithHost(call.host)
代码语言:txt复制
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
代码语言:txt复制
      }
代码语言:txt复制
    }
代码语言:txt复制
    //推进执行
代码语言:txt复制
    promoteAndExecute()
代码语言:txt复制
  }
代码语言:txt复制
//将readyAsyncCalls中合格的请求过渡升级到runningAsyncCalls中
代码语言:txt复制
private fun promoteAndExecute(): Boolean {
代码语言:txt复制
    this.assertThreadDoesntHoldLock()
代码语言:txt复制
    val executableCalls = mutableListOf<AsyncCall>()
代码语言:txt复制
    val isRunning: Boolean
代码语言:txt复制
    synchronized(this) {
代码语言:txt复制
      val i = readyAsyncCalls.iterator()
代码语言:txt复制
      while (i.hasNext()) {
代码语言:txt复制
        val asyncCall = i.next()
代码语言:txt复制
        if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.//运行最大64
代码语言:txt复制
        if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.每个主机最大5
代码语言:txt复制
        i.remove()
代码语言:txt复制
        asyncCall.callsPerHost.incrementAndGet()
代码语言:txt复制
        executableCalls.add(asyncCall)
代码语言:txt复制
        runningAsyncCalls.add(asyncCall)
代码语言:txt复制
      }
代码语言:txt复制
      isRunning = runningCallsCount() > 0
代码语言:txt复制
    }
代码语言:txt复制
    for (i in 0 until executableCalls.size) {
代码语言:txt复制
      val asyncCall = executableCalls[i]
代码语言:txt复制
      asyncCall.executeOn(executorService)
代码语言:txt复制
    }
代码语言:txt复制
    return isRunning
代码语言:txt复制
  }

上面的流程主要是将我们的异步任务放入队列中 并且将可以运行的任务开启运行

RealCall.executeOn()

代码语言:txt复制
fun executeOn(executorService: ExecutorService) {
代码语言:txt复制
      client.dispatcher.assertThreadDoesntHoldLock()
代码语言:txt复制
      var success = false
代码语言:txt复制
      try {
代码语言:txt复制
            //将当前Runnable放到线程池中运行
代码语言:txt复制
        executorService.execute(this)
代码语言:txt复制
        success = true
代码语言:txt复制
      } catch (e: RejectedExecutionException) {
代码语言:txt复制
        val ioException = InterruptedIOException("executor rejected")
代码语言:txt复制
        ioException.initCause(e)
代码语言:txt复制
        noMoreExchanges(ioException)
代码语言:txt复制
        responseCallback.onFailure(this@RealCall, ioException)
代码语言:txt复制
      } finally {
代码语言:txt复制
        if (!success) {
代码语言:txt复制
          client.dispatcher.finished(this) // This call is no longer running!
代码语言:txt复制
        }
代码语言:txt复制
      }
代码语言:txt复制
    }
代码语言:txt复制
override fun run() {
代码语言:txt复制
      threadName("OkHttp ${redactedUrl()}") {
代码语言:txt复制
        var signalledCallback = false
代码语言:txt复制
        timeout.enter()
代码语言:txt复制
        try {
代码语言:txt复制
        //终于到这篇文章的重头戏了
代码语言:txt复制
          val response = getResponseWithInterceptorChain()
代码语言:txt复制
          signalledCallback = true
代码语言:txt复制
          responseCallback.onResponse(this@RealCall, response)
代码语言:txt复制
        } catch (e: IOException) {
代码语言:txt复制
          if (signalledCallback) {
代码语言:txt复制
            // Do not signal the callback twice!
代码语言:txt复制
            Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
代码语言:txt复制
          } else {
代码语言:txt复制
            responseCallback.onFailure(this@RealCall, e)
代码语言:txt复制
          }
代码语言:txt复制
        } catch (t: Throwable) {
代码语言:txt复制
          cancel()
代码语言:txt复制
          if (!signalledCallback) {
代码语言:txt复制
            val canceledException = IOException("canceled due to $t")
代码语言:txt复制
            canceledException.addSuppressed(t)
代码语言:txt复制
            responseCallback.onFailure(this@RealCall, canceledException)
代码语言:txt复制
          }
代码语言:txt复制
          throw t
代码语言:txt复制
        } finally {
代码语言:txt复制
          client.dispatcher.finished(this)
代码语言:txt复制
        }
代码语言:txt复制
      }
代码语言:txt复制
    }
代码语言:txt复制
  }

我们知道OkHttp采用了拦截链模式 看一下何为拦截器模式

借用一下大佬的图(懒得画图了

0 人点赞