OkHttp是Android开发中十分罕用的一个网络申请库了,它反对HTTP1、HTTP2等多种协定,是咱们日常开发中十分给力的帮手。本篇文章基于OkHttp4.9.0版本代码,从OkHttp的创立开始,探索OkHttp是如何发动一次网络申请的。如果你有急躁看完,置信你会对OkHttp有了一个粗浅的理解。如果感觉太长不看的话,看一下总结也是不错的呢(手动滑稽)。

OkHttpClient

应用OkHttp的第一步,天然都是创立OkHttpClient了:

OkHttpClient client = new OkHttpClient();

通过构造方法进入,看看这个OkHttpClient到底是什么:

constructor() : this(Builder()) //默认结构 传入Builder实例class Builder constructor() {    internal var dispatcher: Dispatcher = Dispatcher()//调度器    internal var connectionPool: ConnectionPool = ConnectionPool()//连接池    internal val interceptors: MutableList<Interceptor> = mutableListOf()//整体流程拦截器    internal val networkInterceptors: MutableList<Interceptor> = mutableListOf()//网络申请拦截器  //流程监听器    internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()    internal var retryOnConnectionFailure = true//申请失败是否主动重试    internal var authenticator: Authenticator = Authenticator.NONE//服务器认证设置    internal var followRedirects = true//是否重定向    internal var followSslRedirects = true//是否能够从HTTP重定向到HTTPS    internal var cookieJar: CookieJar = CookieJar.NO_COOKIES//Cookie策略,是否保留Cookie    internal var cache: Cache? = null//缓存配置    internal var dns: Dns = Dns.SYSTEM//Dns配置    internal var proxy: Proxy? = null//代理配置    internal var proxySelector: ProxySelector? = null//代理选择器    internal var proxyAuthenticator: Authenticator = Authenticator.NONE//代理服务器认证设置    internal var socketFactory: SocketFactory = SocketFactory.getDefault()//socket配置    internal var sslSocketFactoryOrNull: SSLSocketFactory? = null//https socket配置    internal var x509TrustManagerOrNull: X509TrustManager? = null    internal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECS    internal var protocols: List<Protocol> = DEFAULT_PROTOCOLS//反对协定配置    internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier//域名校验    internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT//证书链    internal var certificateChainCleaner: CertificateChainCleaner? = null    internal var callTimeout = 0//申请超时配置 0代表不会超时    internal var connectTimeout = 10_000//连贯超时    internal var readTimeout = 10_000//读取超时    internal var writeTimeout = 10_000//写入超时    internal var pingInterval = 0//针对HTTP2和web socket的ping距离    internal var minWebSocketMessageToCompress = RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE    internal var routeDatabase: RouteDatabase? = null  //...

能够看出OkHttpClient实例就是个配置类,当理论发动申请的时候,会采纳用户设置的配置。采纳了Builder模式的设计,让用户更不便的配置这一系列参数,灵便的结构较多的配置。

Request

根底的申请结构类,根本应用:

Request request = new Request.Builder()    .url(ENDPOINT)    .build();

Request类用来形容单次申请的参数信息等,蕴含域名、申请形式、申请头、申请体等一系列信息。通过Builder咱们能够链式调用,比拟优雅的配置这一系列信息。Request类和OkHttpClient类一样,实质是一个形容对象。

Call

申请创立实现,就能够调用OkHttpClient来发动一次申请了,咱们须要通过OkHttpClient的实例办法来发动一次申请:

Call call = client.newCall(request);

Call是一个接口,定义如下:

interface Call : Cloneable {  /** 返回原始的申请信息 */  fun request(): Request      /** 立刻发动一次申请 同步办法 不能在主线程间接调用 */  @Throws(IOException::class)  fun execute(): Response  /** 发动一次异步申请 */  fun enqueue(responseCallback: Callback)  /** 勾销申请 */  fun cancel()  /** 是否被执行过 */  fun isExecuted(): Boolean      /** 是否被勾销了 */  fun isCanceled(): Boolean  /** 申请超时配置策略 */  fun timeout(): Timeout  /** clone这个Call */  public override fun clone(): Call  fun interface Factory {    fun newCall(request: Request): Call  }}

OkHttpClient实现的newCall办法会创立一个RealCall实例,RealCall是利用和网络层的一个连贯桥,它保留了OkHttpClient的援用和原始申请信息。咱们须要通过观察它的实现来追踪网络申请流程。

enqueue

override fun enqueue(responseCallback: Callback) {  //CAS判断是否曾经被执行了  check(executed.compareAndSet(false, true)) { "Already Executed" }    //申请开始告诉  callStart()  //创立异步申请入申请队列  client.dispatcher.enqueue(AsyncCall(responseCallback))}

异步申请办法会创立一个AsyncCall,并调用OkHttpClient配置的Dispatcher解决此申请。

inner class AsyncCall(  private val responseCallback: Callback) : Runnable

AsyncCall实现了Runnable接口,最终会被调度器的线程池进行执行,具体后续再来剖析。

execute

override fun execute(): Response {  //CAS判断是否曾经被执行了  check(executed.compareAndSet(false, true)) { "Already Executed" }  timeout.enter()//申请超时计时  callStart()//申请开始告诉  try {    client.dispatcher.executed(this)//应用调度器退出申请队列    return getResponseWithInterceptorChain()//申请责任链创立  } finally {    client.dispatcher.finished(this)//调度器完结申请  }}

调用了execute之后申请会被退出同步申请队列,而后创立响应责任链发动申请。申请实现会从调度器中移除本次申请。

getResponseWithInterceptorChain

重点来了,OkHttp发动一次申请都须要进行的办法,代码如下:

@Throws(IOException::class)internal 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//网络拦截器  }  //执行流操作(写出申请体、取得响应数据) 负责向服务器发送申请数据、从服务器读取响应数据  //进行http申请报文的封装与申请报文的解析  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)    }  }}

getResponseWithInterceptorChain办法会按肯定的程序构建拦截器列表,这里用到了责任链模式,解决完拦截器列表后,会创立拦截器责任链,拦截器会按程序顺次调用,解决实现之后,再将返回信息返回给用户。

cancel

override fun cancel() {  if (canceled) return // 曾经被勾销 则返回  canceled = true  exchange?.cancel()//勾销io操作  connectionToCancel?.cancel()//敞开socket连贯  eventListener.canceled(this)//事件告诉}

一次申请的勾销其实就是勾销了后续的IO操作和断开连接,而后进行事件告诉。因为调用此办法的时候连贯和IO可能还未开始,所以须要进行判空。

RealInterceptorChain

通过追踪一次同步申请的发动,咱们会发现最终会创立一个RealInterceptorChain实例,并调用了其proceed办法,接下来就来追踪其代码,看看外部到底是如何实现的。

@Throws(IOException::class)override fun proceed(request: Request): Response {  check(index < interceptors.size)//查看下标越界  calls++  if (exchange != null) {    check(exchange.finder.sameHostAndPort(request.url)) {      "network interceptor ${interceptors[index - 1]} must retain the same host and port"    }    check(calls == 1) {      "network interceptor ${interceptors[index - 1]} must call proceed() exactly once"    }  }  // 下一个须要执行的拦截器,index+1  val next = copy(index = index + 1, request = request)  val interceptor = interceptors[index]    //调用拦截器的intercept办法,传入下一个责任链  @Suppress("USELESS_ELVIS")  val response = interceptor.intercept(next) ?: throw NullPointerException(      "interceptor $interceptor returned null")  if (exchange != null) {    check(index + 1 >= interceptors.size || next.calls == 1) {      "network interceptor $interceptor must call proceed() exactly once"    }  }  check(response.body != null) { "interceptor $interceptor returned a response with no body" }  return response}

proceed的办法也不简单,外面有一系列的检测办法,外围代码其实只有几行,大抵逻辑如下:

  • 1、数组下标+1,取出下一个拦截器,而后复制并创立新的责任链
  • 2、获取以后下标的拦截器
  • 3、调用以后拦截器的intercept办法,并传入下一个拦截器责任链实例

    为什么能够链式调用上来呢?这里能够看一下Interceptor的接口定义

    fun interface Interceptor {  @Throws(IOException::class)  fun intercept(chain: Chain): Response}

    Interceptor只有一个办法,实现了intercept办法后须要调用传递进来的Chain,下面咱们曾经晓得了这是下一个拦截器。调用了chain.proceed办法返回Response,将逻辑交由下一个拦截器解决。

Dispatcher

再回过头看异步申请,下面咱们能够晓得,一次异步申请最终是调用了dispatcher.enqueue的办法,那么Dispatcher负责了什么呢?

Dispatcher次要负责异步申请的执行逻辑。Dispatcher中能够定义maxRequests来治理最大并发申请数量,maxRequestsPerHost来确定单个host的最大并发申请数量。

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) {      //找到此host存在的其余call      val existingCall = findExistingCallWithHost(call.host)      //如果找到了 复用其余call的计数器      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)    }  }  //理论的去执行  promoteAndExecute()}

调用了enqueue办法后,会先上锁,而后在异步队列readyAsyncCalls中退出此申请,再查看以后申请的host有无其余call,找到了,则复用其余call的申请计数器。最初走到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()      if (runningAsyncCalls.size >= this.maxRequests) break // 超过最大申请数量,跳出循环      if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue //单个host申请下限,跳过此申请      i.remove()      asyncCall.callsPerHost.incrementAndGet()//cas 计数      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}

promoteAndExecute办法会遍历异步申请队列,如果以后并发申请数量下限了,则会跳出,不执行任何申请。如果一个host的并发申请数量达到了下限,会跳过此申请。最初,为能够执行的申请进行调用。如果用户没有自行设置线程池,则Dispatcher外部会创立一个的线程池用来执行异步网络申请。

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) {      //申请失败了也要告诉dispatcher      client.dispatcher.finished(this) // This call is no longer running!    }  }}

下面我也说过了,AsyncCall自身实现了Runable接口,这里被执行之后,会调用run办法,执行外部逻辑,具体逻辑和同步申请的逻辑基本一致,这里就不再赘述。申请实现后,不论后果成功失败,都会调用Dispatcherfinished办法。

internal fun finished(call: AsyncCall) {  call.callsPerHost.decrementAndGet()//cas 计数  finished(runningAsyncCalls, call)}private fun <T> finished(calls: Deque<T>, call: T) {    val idleCallback: Runnable?    synchronized(this) {      //从队列中移除当前任务      if (!calls.remove(call)) throw AssertionError("Call wasn't in-flight!")      idleCallback = this.idleCallback    }        //尝试执行其余工作    val isRunning = promoteAndExecute()    if (!isRunning && idleCallback != null) {      idleCallback.run()//如果以后闲置 进行告诉    }  }

finished办法被调用后会从申请队列中移除以后申请,再尝试执行残余的申请。Dispatcher外部也保护了同步申请队列,当同步申请实现之后也会走相似的逻辑。

RetryAndFollowUpInterceptor

这个拦截器用来进行谬误重试和重定向。拦截器外部是一个死循环。

try {  response = realChain.proceed(request)  newExchangeFinder = true} catch (e: RouteException) {  // The attempt to connect via a route failed. The request will not have been sent.  if (!recover(e.lastConnectException, call, request, requestSendStarted = false)) {    throw e.firstConnectException.withSuppressed(recoveredFailures)  } else {    recoveredFailures += e.firstConnectException  }  newExchangeFinder = false  continue} catch (e: IOException) {  // An attempt to communicate with a server failed. The request may have been sent.  if (!recover(e, call, request, requestSendStarted = e !is ConnectionShutdownException)) {    throw e.withSuppressed(recoveredFailures)  } else {    recoveredFailures += e  }  newExchangeFinder = false  continue}

网络申请的异样会被catch,而后会判断是否要从新进行申请。如果能失常走上来,则会对重定向相干进行判断,创立对应的申请。

ExchangeFinder

这个类在RetryAndFollowUpInterceptor中调用call.enterNetworkInterceptorExchange(request, newExchangeFinder)后被创立。这个类用来在RealConnectionPool连接池中找到一个以后申请可用的RealConnection,而后开启连贯,进行接下来的IO操作。

ConnectInterceptor

这个拦截器会对指定的服务器关上连贯,而后执行其余的拦截器

@Throws(IOException::class)override fun intercept(chain: Interceptor.Chain): Response {  val realChain = chain as RealInterceptorChain  val exchange = realChain.call.initExchange(chain)//初始化Exchange  val connectedChain = realChain.copy(exchange = exchange)//为之后的责任链传入Exchange  return connectedChain.proceed(realChain.request)}

这个拦截器会调用RealCallinitExchange办法,并把以后的责任链传递过过来。

internal fun initExchange(chain: RealInterceptorChain): Exchange {  synchronized(this) {    check(expectMoreExchanges) { "released" }    check(!responseBodyOpen)    check(!requestBodyOpen)  }  val exchangeFinder = this.exchangeFinder!!  //用之前RetryAndFollowUpInterceptor传入的finder寻找编码器  val codec = exchangeFinder.find(client, chain)  //采纳对应的编码器创立Exchange  val result = Exchange(this, eventListener, exchangeFinder, codec)  this.interceptorScopedExchange = result  this.exchange = result  synchronized(this) {    this.requestBodyOpen = true    this.responseBodyOpen = true  }  if (canceled) throw IOException("Canceled")  return result}

initExchange里会应用ExchangeFinder来寻找一个ExchangeCodec,这是一个网络申请的编码器,针对不同的协定会采纳不同的形式来进行编码传输。

fun find(  client: OkHttpClient,  chain: RealInterceptorChain): ExchangeCodec {  try {    //寻找一个衰弱的连贯    val resultConnection = findHealthyConnection(        connectTimeout = chain.connectTimeoutMillis,        readTimeout = chain.readTimeoutMillis,        writeTimeout = chain.writeTimeoutMillis,        pingIntervalMillis = client.pingIntervalMillis,        connectionRetryEnabled = client.retryOnConnectionFailure,        doExtensiveHealthChecks = chain.request.method != "GET"    )    //创立对应的编码器    return resultConnection.newCodec(client, chain)  } catch (e: RouteException) {    trackFailure(e.lastConnectException)    throw e  } catch (e: IOException) {    trackFailure(e)    throw RouteException(e)  }}

ExchangeFinder的find办法会去尝试找到一个与服务器之间的连贯。追踪findHealthyConnection代码咱们会发现它外部是一个死循环,一直的调用findConnection办法去寻找一个可用的连贯。findConnection的代码就比拟长了,这里就不贴出来了。大略的逻辑就是优先从连接池中找连贯,如果没有找到可用的连贯,则会创立一个RealConnection对象,存入缓存池中。

RealConnection

RealConnection是OkHttp理论建设连贯的中央。通过connect办法建设与服务器的链接。通过追踪源码咱们会发现RealConnection底层还是通过Socket建设连贯的。

@Throws(IOException::class)private fun connectSocket(  connectTimeout: Int,  readTimeout: Int,  call: Call,  eventListener: EventListener) {  val proxy = route.proxy  val address = route.address  val rawSocket = when (proxy.type()) {    Proxy.Type.DIRECT, Proxy.Type.HTTP -> address.socketFactory.createSocket()!!    else -> Socket(proxy)  }  this.rawSocket = rawSocket  eventListener.connectStart(call, route.socketAddress, proxy)  rawSocket.soTimeout = readTimeout  try {    //针对不同的平台进行适配    Platform.get().connectSocket(rawSocket, route.socketAddress, connectTimeout)  } catch (e: ConnectException) {    throw ConnectException("Failed to connect to ${route.socketAddress}").apply {      initCause(e)    }  }  try {    //应用OkIO开启io    source = rawSocket.source().buffer()    sink = rawSocket.sink().buffer()  } catch (npe: NullPointerException) {    if (npe.message == NPE_THROW_WITH_NULL) {      throw IOException(npe)    }  }}

CallServerInterceptor

这是所有拦截器中的最初一个拦截器。在这个拦截器里会进行IO操作与服务器交互。OkHttp底层应用了OkIO来进行IO操作。

@Throws(IOException::class)override fun intercept(chain: Interceptor.Chain): Response {  val realChain = chain as RealInterceptorChain  val exchange = realChain.exchange!!//替换数据的桥梁,具体将具体替换逻辑散发到不同的实现  val request = realChain.request  val requestBody = request.body  val sentRequestMillis = System.currentTimeMillis()  var invokeStartEvent = true  var responseBuilder: Response.Builder? = null  var sendRequestException: IOException? = null  try {    //写申请头 最终会调用具体的ExchangeCodec去实现    exchange.writeRequestHeaders(request)    if (HttpMethod.permitsRequestBody(request.method) && requestBody != null) {      //遇到HTTP/1.1 中约定的Expect: 100-continue 会间接发动申请      if ("100-continue".equals(request.header("Expect"), ignoreCase = true)) {        exchange.flushRequest()//发送申请报文        responseBuilder = exchange.readResponseHeaders(expectContinue = true)//读取响应头        exchange.responseHeadersStart()//事件告诉        invokeStartEvent = false      }      if (responseBuilder == null) {        if (requestBody.isDuplex()) {             //针对HTTP2协定的双工申请体 先发送申请头          exchange.flushRequest()          val bufferedRequestBody = exchange.createRequestBody(request, true).buffer()          requestBody.writeTo(bufferedRequestBody)//写入申请体        } else {          val bufferedRequestBody = exchange.createRequestBody(request, false).buffer()          requestBody.writeTo(bufferedRequestBody)//写入申请体          bufferedRequestBody.close()        }      } else {        //没有申请体        exchange.noRequestBody()        if (!exchange.connection.isMultiplexed) {          exchange.noNewExchangesOnConnection()        }      }    } else {      //没有申请体      exchange.noRequestBody()    }    if (requestBody == null || !requestBody.isDuplex()) {      exchange.finishRequest()//完结申请写入并发送    }  } catch (e: IOException) {    if (e is ConnectionShutdownException) {      throw e // No request was sent so there's no response to read.    }    if (!exchange.hasFailure) {      throw e // Don't attempt to read the response; we failed to send the request.    }    sendRequestException = e  }  try {    if (responseBuilder == null) {      //读取响应头      responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!      if (invokeStartEvent) {        //事件告诉        exchange.responseHeadersStart()        invokeStartEvent = false      }    }    //构建Response    var response = responseBuilder        .request(request)        .handshake(exchange.connection.handshake())        .sentRequestAtMillis(sentRequestMillis)        .receivedResponseAtMillis(System.currentTimeMillis())        .build()    var code = response.code    if (code == 100) {      // Server sent a 100-continue even though we did not request one. Try again to read the      // actual response status.      responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!      if (invokeStartEvent) {        exchange.responseHeadersStart()      }      //如果code 是100则从新读取      response = responseBuilder          .request(request)          .handshake(exchange.connection.handshake())          .sentRequestAtMillis(sentRequestMillis)          .receivedResponseAtMillis(System.currentTimeMillis())          .build()      code = response.code    }      //事件告诉    exchange.responseHeadersEnd(response)    response = if (forWebSocket && code == 101) {      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.      response.newBuilder()          .body(EMPTY_RESPONSE)          .build()    } else {      //写入ResponseBody      response.newBuilder()          .body(exchange.openResponseBody(response))          .build()    }    //收到敞开连贯的Header 敞开IO    if ("close".equals(response.request.header("Connection"), ignoreCase = true) ||        "close".equals(response.header("Connection"), ignoreCase = true)) {      exchange.noNewExchangesOnConnection()    }    if ((code == 204 || code == 205) && response.body?.contentLength() ?: -1L > 0L) {      throw ProtocolException(          "HTTP $code had non-zero Content-Length: ${response.body?.contentLength()}")    }    //返回Response    return response  } catch (e: IOException) {    if (sendRequestException != null) {      sendRequestException.addSuppressed(e)      throw sendRequestException    }    throw e  }}

CallServerInterceptorintercept办法很长,不过逻辑并不简单。大抵流程如下:

  • 1、依据Request的配置写入申请行和申请头。
  • 2、依据Method判断是否反对申请体,如果反对则尝试写入申请体并发送申请报文,否则间接发送
  • 3、读取响应报文,构建Response
  • 4、读取响应体,为Response写入ResponseBody
  • 5、判断是否要敞开连贯
  • 6、返回Response

因为CallServerInterceptor是最初一个Interceptor,所以返回的Response会一级一级的向上传递,最初用户就能拿到包装后的响应Response了。

BridgeInterceptor

这个拦截器是利用和网络交互的一个桥梁。首先他会获取Request里的信息,依据申请内容在Request中增加或者一些申请头,这些都是用户未感知到的。同时这个拦截器还会读取Cookie配置,如果有Cookie信息,也会通过申请头带到服务端。

Request信息欠缺后,会调用后续的责任链去解决欠缺的Request,并期待后续的返回。

        val networkResponse = chain.proceed(requestBuilder.build())//期待响应    cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)//解决Cookie    val responseBuilder = networkResponse.newBuilder()        .request(userRequest)//将原始申请信息放入Response    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")        //解决ResponseBody        responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))      }    }        //返回欠缺的Response    return responseBuilder.build()

收到后续的返回后,会对Response进行解决,并精简一些响应头。最终将欠缺的Response回传给用户。很多操作都是用户无感知的实现的,深藏功与名。

Response

这就没什么好说的了吧?在通过一些列链式调用和解决,最终用户能够拿到一个Response对象。在这里用户就能够拿到申请的各种信息以及相应,剩下的就交给用户自行处理了。在用户拿到Response后,一次网络申请也算实现啦!

总结

话不多说,先上图

再来文字总结一下,OkHttpClinent类是一个网络申请的配置类,咱们通过构建Request来形容咱们的申请信息,接着应用newCall办法能够创立一个RealCall实例。

RealCall能够抉择同步执行或者是异步执行,他是咱们与网络交互的一个桥梁。如果是同步申请,则会间接调用gerResponseWithInterceptorChain()办法创立拦截器责任链。如果是异步申请,则会散发到DispatcherDispatcher最终会应用线程池执行这个申请,最终也还是会走到gerResponseWithInterceptorChain()办法。

gerResponseWithInterceptorChain()办法中,会将所有的拦截器依照肯定程序封装进一个列表,构建一个RealInterceptorChainproceed办法会调用各个拦截器的intercept办法,拦截器在解决实现本人的职责后,持续调用proceed办法。

RetryAndFollowUpInterceptor负责处理错误重试和重定向,BridgeInterceptor负责包装申请和返回数据,CacheInterceptor负责缓存的解决,而ConnectInterceptor则真正的关上了连贯,最初通过CallServerInterceptor进行网络IO,发送和解决报文。

OkHttp底层采纳了Socket进行网络连接,采纳OkIO进行网络IO,有连接池逻辑,会存储RealConnection实例,缩小过多连贯产生的开销。

浏览源码不难,难的是写源码时候应该具备的思维。通过浏览OkHttp源码能够让咱们学习到很多设计思维:通过Builder模式构建简单对象、通过责任链模式有序的散发工作和回传、性能的形象等等。好的开源框架的源码浏览真的能让咱们播种很多,咱们应该学以致用,这样就算有一天他人让你做一个相似的性能时候,你也不会毫无脉络。心愿这篇文章能让你有所播种,当然我更倡议你本人浏览一遍源码,兴许会有不一样的播种。

能看到这里也不容易,棘手给个赞吧,欢送分享不同的见解(#^.^#)

视频:
资深架构师带你逐题详解Android大厂精选高频面试题:OkHttp的应用流程;OkHttp散发器原理
OkHttp散发器线程池上;OkHttp散发器线程池下;OkHttp拦截器责任链设计模式

原文: https://juejin.cn/post/6909445385266135048#comment