OkHttp网络请求流程

Quibbler 2021-3-16 1506

OkHttp网络请求流程


        经过前面多篇博客的铺垫,终于来了。让我们继续深入OkHttp源码,了解OkHttp网络请求的实现。

    val requestBuilder: Request.Builder = Request.Builder()
    ...
    val request: Request = requestBuilder.build()
    val call: Call = okHttpClient.newCall(request)

        在OkHttp的基本用法一文中我们了解到,拿到Call实例后,有两种网络请求:异步和同步。



1、异步请求

        从Callenqueue(responseCallback: Callback)方法开始:


        从OkHttpClient调用newCall(Request)方法获取Call实例,返回的是RealCall对象:

    /** Prepares the [request] to be executed at some point in the future. */
    override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)

        RealCall实现了Call接口,enqueue(responseCallback: Callback)方法实现如下:

    override fun enqueue(responseCallback: Callback) {
        check(executed.compareAndSet(false, true)) { "Already Executed" }
        callStart()
        client.dispatcher.enqueue(AsyncCall(responseCallback))
    }

        通过构造RealCall中的innerAsyncCall封装当前的RealCallCallback回调。并将其放入Dispatcher调度器中的异步等待队列readyAsyncCalls

  internal fun enqueue(call: AsyncCall) {
    synchronized(this) {
      readyAsyncCalls.add(call)
      // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
      // the same host.
      if (!call.call.forWebSocket) {
        val existingCall = findExistingCallWithHost(call.host)
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
      }
    }
    promoteAndExecute()
  }

        调用promoteAndExecute()方法推进任务队列的执行。

  private fun promoteAndExecute(): Boolean {
    this.assertThreadDoesntHoldLock()
    val executableCalls = mutableListOf<AsyncCall>()
    val isRunning: Boolean
    synchronized(this) {
      val i = readyAsyncCalls.iterator()
      while (i.hasNext()) {
        val asyncCall = i.next()
        ...
        //将接下来执行的AsyncCall放入执行队列runningAsyncCalls中
        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)方法,传入Dispatcher中的执行器ExecutorService

    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!
        }
      }
    }

        看到通过Executor执行自身,毫无疑问,AsyncCall继承自Runnable,直接看它的run()方法实现:

  override fun run() {
      ...
      try {
        val response = getResponseWithInterceptorChain()
        signalledCallback = true
        responseCallback.onResponse(this@RealCall, response)
      } catch (e: IOException) {
        ...
      } catch (t: Throwable) {
        ...
      } finally {
        //最后,将执行过的AsyncCall从开始加入的runningAsyncCalls中移除
        client.dispatcher.finished(this)
      }
  }

        在run()中调用OkHttp网络请求核心方法:getResponseWithInterceptorChain(),经过层层拦截器调用链获取网络请求。这里暂不对该方法展开分析,在OkHttp拦截器Interceptor一文中详细分析。

        拿到Response网络请求响应,回调直接创建网络请求时构造的Callback实例

  interface Callback {
    fun onFailure(call: Call, e: IOException)
    fun onResponse(call: Call, response: Response)
  }

        最后,将执行过的异步任务从异步执行队列runningAsyncCalls中移除。

  /** Used by [AsyncCall.run] to signal completion. */
  internal fun finished(call: AsyncCall) {
    call.callsPerHost.decrementAndGet()
    finished(runningAsyncCalls, call)
  }



2、同步请求

        同步请求逻辑比异步请求要简单直接一些。


        直接执行Call实例的execute()方法,该方法在RealCall类中实现:

  override fun execute(): Response {
    check(executed.compareAndSet(false, true)) { "Already Executed" }
    timeout.enter()
    callStart()
    try {
      client.dispatcher.executed(this)
      return getResponseWithInterceptorChain()
    } finally {
      client.dispatcher.finished(this)
    }
  }

        接着调用Dispatcherexecute()方法,是不是用Dispatcher执行呢?不是,只是将RealCall放到runningSyncCalls同步执行队列中,请求完毕最后在finally中移除。

  /** Used by [Call.execute] to signal it is in-flight. */
  @Synchronized internal fun executed(call: RealCall) {
    runningSyncCalls.add(call)
  }

        紧接着才是getResponseWithInterceptorChain()OkHttp网络请求核心方法。该方法封装网络请求、拦截器、连接池等等,返回Response响应。所以直接执行execute()要放到子线程中。

        


不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com