OkHttp-4.4.0 源码阅读

1.同步异步流程上的梳理

1.1 enqueue 异步方法

val okHttpclient = OkHttpClient.Builder().build()
val request = Request.Builder().build()
okHttpclient.newCall(request).enqueue(object : Callback {
    
    
    override fun onFailure(call: Call, e: IOException) {
    
    
        TODO("Not yet implemented")
    }

    override fun onResponse(call: Call, response: Response) {
    
    
        TODO("Not yet implemented")
    }
})

使用上就是以上代码。初始化一个client和request。这里都是使用的建造者模式,然后创建call对象,调用异步方法。首先看看创建call对象的方法newCall。

// 构造器中3个参数 
// 1、client:OkHttpClient 这个就不赘述了
// 2、originalRequest:Request 请求,最原始的请求,还有没有经过责任链中的拦截处理过的请求
// 3、forwebSocket:Boolean 是否为webSocket
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)

在这里仅仅只是初始化的是一个RealCall对象,接着走看看同步方法RealCall.enqueue

override fun enqueue(responseCallback: Callback) {
    
    
  synchronized(this) {
    
    
    check(!executed) {
    
     "Already Executed" }
    executed = true
  }
  callStart()
  // 这里是关键代码,调用了分发器的enqueue方法,并且实例了AsyncCall对象并把回调传入了
  client.dispatcher.enqueue(AsyncCall(responseCallback))
}

1.2 Dispacther

这里没有直接按照代码方法走下去,而是先介绍这个对象。这个对象的主要职责是:做线程调度的,内部线程调度使用的是ExecutorService,介绍一下关键的几个参数。

// 最大承受多少同时的网络请求数,默认是64
@get:Synchronized var maxRequests = 64
// 对相同的host支持的同时请求数量,默认5
@get:Synchronized var maxRequestsPerHost = 5
// 这个就是线程服务
@get:JvmName("executorService") val executorService: ExecutorService
// 等待的异步请求队列
private val readyAsyncCalls = ArrayDeque<AsyncCall>()
// 正在请求的异步请求队列
private val runningAsyncCalls = ArrayDeque<AsyncCall>()
// 正在运行的同步队列
private val runningSyncCalls = ArrayDeque<RealCall>()

1.2.1 Dispatcher.enqueue方法

接着从Dispatcher的enqueue方法走。

internal fun enqueue(call: AsyncCall) {
    
    
  synchronized(this) {
    
    
    // 对请求的call,先直接放入到等待队列中
    readyAsyncCalls.add(call)
    
    if (!call.call.forWebSocket) {
    
    
      // 这里是设置call的相同主机的请求数
      val existingCall = findExistingCallWithHost(call.host)
      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
    }
  }
  promoteAndExecute()
}

接着就调用了promoteAndExecute方法。

1.2.2 promoteAndExecute

主要实现内容:把符合条件的没有被执行的call全部推举出来去执行,执行调用了AsyncCall的executeOn方法

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 // Max capacity.
      // 相同host最大同时请求数判断
      if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.
      // 如果不满足以上的2个判断,就会被添加到新的一个List和runningAsyncCalls(正在运行的队列)
      i.remove()
      asyncCall.callsPerHost.incrementAndGet()
      executableCalls.add(asyncCall)
      runningAsyncCalls.add(asyncCall)
    }
    isRunning = runningCallsCount() > 0
  }

  // 这就很能体现新建一个List的作用了,将满足条件可请求的call进行请求。
  for (i in 0 until executableCalls.size) {
    
    
    val asyncCall = executableCalls[i]
    // 将call拿去执行
    asyncCall.executeOn(executorService)
  }

  return isRunning
}

1.2.3 AsyncCall.executeOn

代码中主要调用了executorService的execute方法,AsyncCall实现了Runnable,所以在启动后会调用此类中的run方法。

internal inner class AsyncCall(
  private val responseCallback: Callback
) : Runnable {
    
    
      fun executeOn(executorService: ExecutorService) {
    
    
        client.dispatcher.assertThreadDoesntHoldLock()

        var success = false
        try {
    
    
          // 在这里直接就调用了execute方法
          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!
          }
        }
      }

      override fun run() {
    
    
        threadName("OkHttp ${redactedUrl()}") {
    
    
          var signalledCallback = false
          timeout.enter()
          try {
    
    
            // 这里到了okhttp中的关键代码,责任链模式
            val response = getResponseWithInterceptorChain()
            signalledCallback = true
            // 调用响应回调
            responseCallback.onResponse(this@RealCall, response)
          } catch (e: IOException) {
    
    
            if (signalledCallback) {
    
    
              // Do not signal the callback twice!
              Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
            } else {
    
    
              // 调用失败回调
              responseCallback.onFailure(this@RealCall, e)
            }
          } catch (t: Throwable) {
    
    
            cancel()
            if (!signalledCallback) {
    
    
              val canceledException = IOException("canceled due to $t")
              canceledException.addSuppressed(t)
              // 调用失败回调
              responseCallback.onFailure(this@RealCall, canceledException)
            }
            throw t
          } finally {
    
    
            client.dispatcher.finished(this)
          }
        }
      }
    }
}

到这整个异步流程就走通了,从设置回调,到响应回调。

1.2 execute 同步方法

override fun execute(): Response {
    
    
  synchronized(this) {
    
    
    check(!executed) {
    
     "Already Executed" }
    executed = true
  }
  timeout.enter()
  callStart()
  try {
    
    
    client.dispatcher.executed(this) // 直接将call放入到正在请求队列中
    return getResponseWithInterceptorChain()
  } finally {
    
    
    client.dispatcher.finished(this)
  }
}

同步就相当直接了,直接放入到请求队列中,然后走到了责任链中去执行网络请求

2.责任链的梳理

2.1 getResponseWithInterceptorChain

这个方法可以理解分为三块,第一块是将链放入链条中,第二块是RealInterceptorChain对象,第三块是跑链条。

@Throws(IOException::class)
internal 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(
      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)
    }
  }
}

责任链会按照第一块组装的list的顺序执行链,简单介绍一下5个责任链

2.1.1 RetryAndFollowUpInterceptor

在网络请求后:错误后的重试以及重定向的请求处理。

2.1.2 BridgeInterceptor

在网络请求前:封装了Request的Header,如Content-type、Content-Length等等

在网络请求后:如果属于gzip,会帮我们解压

2.1.3 CacheInterceptor

在网络请求前:从cache中能否拿到可用的,拿到就直接返回了,不网络请求了

在网络请求后:将请求及响应相关的存入缓存

2.1.4 ConnectInterceptor

创建连接,不总是去创建连接,是先去连接池中找是否存在可用的连接,有则直接使用,无则在创建,当连接使用完后,也不是直接销毁。

2.1.5 CallServiceInterceptor

发请求、读响应。内部是一系列的I/O操作

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

在这里插入图片描述
二、源码解析合集
在这里插入图片描述

三、开源框架合集
在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

猜你喜欢

转载自blog.csdn.net/weixin_43440181/article/details/130976462