Android源码分析-OkHttp-4-执行Call

277 阅读2分钟

同步执行任务

任务开始执行,由client中创建的线程调度器,调度至当前线程执行
//任务开始
newCall.execute().use { response-> }

override fun execute(): Response {
    synchronized(this) {
      check(!executed) { "Already Executed" }
      executed = true
    }
    transmitter.timeoutEnter()
    transmitter.callStart()
    try {
    //由client中创建的线程调度器,调度至当前线程执行
      client.dispatcher.executed(this)
      return getResponseWithInterceptorChain()
    } finally {
      client.dispatcher.finished(this)
    }
}
调度至runningSyncCalls队列
/** Used by `Call#execute` to signal it is in-flight. */
@Synchronized internal fun executed(call: RealCall) {
    runningSyncCalls.add(call)
}

这里三个队列解释一下,同步任务直接调度到开始执行的队列,异步任务需使用AsyncCall包装一层,再等待线程调度

  • readyAsyncCalls:准备好的异步任务队列,按顺序执行
  • runningAsyncCalls:开始执行的异步任务队列,包括未结束的已经取消的任务
  • runningSyncCalls:开始执行的同步任务队列,包括未结束的已经取消的任务
getResponseWithInterceptorChain

然后RealCall真正执行到getResponseWithInterceptorChain方法开始网络请求。

@Throws(IOException::class)
  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(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)
      }
    }
  }
拦截器链
  1. client.interceptors:公共拦截器
  2. RetryAndFollowUpInterceptor:重定向拦截器,故障恢复,如果已经取消的任务,拦截到后会抛出IOException
  3. BridgeInterceptor:网络响应拦截器,封装请求,封装响应内容
  4. CacheInterceptor:缓存拦截器,管理缓存
  5. ConnectInterceptor:负责和服务器建立连接,连接池等
  6. CallServerInterceptor:负责向服务器发送请求数据、从服务器读取响应数据(实际网络请求)
  7. RealInterceptorChain:RealCall本身也可以认为是一个拦截器

拦截器按顺序拼接

  1. 打开连接
  2. 响应缓存
  3. 若缓存未命中启动网络请求
  4. 网络请求结束后判定是否重定向
  5. 最后进入自定义拦截器中,用于获取统计信息,日志打印等
拦截器

观察,修改请求,并可能使发出的请求短路,相应的响应又返回。通常,拦截器在请求或响应上添加,删除或转换标头。

第一个拦截器开始执行,val chain = RealInterceptorChain,RealCall本身的拦截器,
val chain = RealInterceptorChain(interceptors, transmitter, null, 0, originalRequest, this,
        client.connectTimeoutMillis, client.readTimeoutMillis, client.writeTimeoutMillis)
执行proceed方法,index参数为0, 调用到index为1的拦截器的intercept方法
@Throws(IOException::class)
  fun proceed(request: Request, transmitter: Transmitter, exchange: Exchange?): Response {
    // 调用下一个拦截器,启动拦截事件
    val next = RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout)
    val interceptor = interceptors[index]//定位拦截器

    @Suppress("USELESS_ELVIS")//启动拦截器,可以称为递归将所有拦截器遍历一遍
    val response = interceptor.intercept(next) ?: throw NullPointerException(
        "interceptor $interceptor returned null")

    return response
  }
假定不存在用户自定义的拦截器,index为1的拦截器为RetryAndFollowUpInterceptor,在intercept方法中会调用到其process方法
val realChain = chain as RealInterceptorChain
response = realChain.proceed(request, transmitter, null)
此时开始调用index为2的拦截器:BridgeInterceptor的intercept方法中增加一些请求头部信息,比如Content-Type、Connection、Cookie、User-Agent等,然后调用process方法启动下一个拦截器
if (userRequest.header("User-Agent") == null) {
  requestBuilder.header("User-Agent", userAgent)
}
val networkResponse = chain.proceed(requestBuilder.build())
index为3的拦截器:CacheInterceptor,从CacheStrategy中读取缓存信息,必须网络请求后,才响应缓存功能,由服务器告知是否响应缓存
//如果网络不正常,并且缓存不正确,直接返回空响应
if (networkRequest == null && cacheResponse == null) {
  return Response.Builder()
      .request(chain.request())
      .protocol(Protocol.HTTP_1_1)
      .code(HTTP_GATEWAY_TIMEOUT)
      .message("Unsatisfiable Request (only-if-cached)")
      .body(EMPTY_RESPONSE)
      .sentRequestAtMillis(-1L)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build()
}
// 网络不正常,返回空
if (networkRequest == null) {
  return cacheResponse!!.newBuilder()
      .cacheResponse(stripBody(cacheResponse))
      .build()
}

var networkResponse: Response? = null
try {
  networkResponse = chain.proceed(networkRequest)
} finally {
  // If we're crashing on I/O or otherwise, don't leak the cache body.
  if (networkResponse == null && cacheCandidate != null) {
    cacheCandidate.body?.closeQuietly()
  }
}
index为4的拦截器:ConnectInterceptor代码比较少,打开与目标服务器的连接,然后进入下一个拦截器,此处初始化exchange类相当于HttpClient吧
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val realChain = chain as RealInterceptorChain
val request = realChain.request()
val transmitter = realChain.transmitter()

// We need the network to satisfy this request. Possibly for validating a conditional GET.
val doExtensiveHealthChecks = request.method != "GET"
val exchange = transmitter.newExchange(chain, doExtensiveHealthChecks)

return realChain.proceed(request, transmitter, exchange)
}
下一个拦截器为index5的:client.networkInterceptors自定义的网络拦截器
下一个拦截器为index6的:CallServerInterceptor实际网络请求,此处先不深究网络请求过程,仅分析拦截器流程,网络请求成功后,将响应返回到前一个拦截器
通过用户自定义的网络拦截器,可以格式化输出信息,时间统计等,然后再返回到前一个拦截器,ConnectInterceptor拦截器并未作处理,直接返回至CacheInterceptor
CacheInterceptor先判定缓存是否有效,如果仍有效(networkResponse?.code==HTTP_NOT_MODIFIED),则读取缓存,如果缓存已经失效,则打开连接,读取服务端响应,并且当缓存允许时,将响应写入缓存,然后继续响应上一个拦截器
// If we have a cache response too, then we're doing a conditional get.
if (cacheResponse != null) {
  if (networkResponse?.code == HTTP_NOT_MODIFIED) {
    val response = cacheResponse.newBuilder()
        .headers(combine(cacheResponse.headers, networkResponse.headers))
        .sentRequestAtMillis(networkResponse.sentRequestAtMillis)
        .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis)
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build()

    networkResponse.body!!.close()

    // Update the cache after combining headers but before stripping the
    // Content-Encoding header (as performed by initContentStream()).
    cache!!.trackConditionalCacheHit()
    cache.update(cacheResponse, response)
    return response
  } else {
    cacheResponse.body?.closeQuietly()
  }
}

val response = networkResponse!!.newBuilder()
    .cacheResponse(stripBody(cacheResponse))
    .networkResponse(stripBody(networkResponse))
    .build()

if (cache != null) {
  if (response.promisesBody() && CacheStrategy.isCacheable(response, networkRequest)) {
    // Offer this request to the cache.
    val cacheRequest = cache.put(response)
    return cacheWritingResponse(cacheRequest, response)
  }
}

return response
BridgeInterceptor,将默认gzip压缩到响应进行解压,然后继续响应上一个拦截器
cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)

val responseBuilder = networkResponse.newBuilder()
    .request(userRequest)

if (transparentGzip &&
    "gzip".equals(networkResponse.header("Content-Encoding"), ignoreCase = true) &&
    networkResponse.promisesBody()) {
  val responseBody = networkResponse.body
  if (responseBody != null) {
    val gzipSource = GzipSource(responseBody.source())
    val strippedHeaders = networkResponse.headers.newBuilder()
        .removeAll("Content-Encoding")
        .removeAll("Content-Length")
        .build()
    responseBuilder.headers(strippedHeaders)
    val contentType = networkResponse.header("Content-Type")
    responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))
  }
}

return responseBuilder.build()
RetryAndFollowUpInterceptor得到响应后,响应传递给最基层的client.interceptors后,响应将返回到请求处,到此一个同步网络请求结束

异步任务执行

newCall.enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) {
    }

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

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

异步调用将RealCall包装为内部类AsyncCall,携带callback参数,并将其添加至readyAsyncCalls准备好的异步任务队列,发起一次由Dispatcher进行调度执行在指定的线程池中,AsyncCall实现了Runnable,run方法中getResponseWithInterceptorChain方法实现与同步执行一致了

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

到此,OkHttp执行过程描述完毕