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机器人,可以解答大家在工作上或者是技术上的问题