前言
本文基于okhttp3:4.9.3进行分析:
implementation("com.squareup.okhttp3:okhttp:4.9.3")
请求流程:
- 创建OkHttpClient对象:
OkHttp.Build().build()
- 创建Reques对象:
Request.Builder().build()
- 异步请求:
client.newCall(request).enqueue()
newCall(request)
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
OkhttpClient.newCall(request)
其实就是生成一个RealCall
对象,接着去看RealCall.enqueue()
方法。
RealCall.enqueue()
override fun enqueue(responseCallback: Callback) {
check(executed.compareAndSet(false, true)) { "Already Executed" }
callStart() ①
client.dispatcher.enqueue(AsyncCall(responseCallback)) ②
}
private fun callStart() {
this.callStackTrace = Platform.get().getStackTraceForCloseable("response.body().close()")
eventListener.callStart(this)
}
①处并不是去执行真正的网络请求,我们在callStart()
方法中可以看到,只是执行了eventListener.callStart()
,这个Listener只是用来记录HTTP调用的数量、大小和持续时间,下面是EventListener的注释信息。
Listener for metrics events. Extend this class to monitor the quantity, size, and duration of your application’s HTTP calls.
②处才是我们需要关注的流程,接着我们进入Dispatcher.enqueue()
方法。
Dispatcher.enqueue()
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() ②
}
private fun promoteAndExecute(): Boolean {
this.assertThreadDoesntHoldLock()
val executableCalls = mutableListOf<AsyncCall>()
val isRunning: Boolean
synchronized(this) {
// 遍历待执行的队列,取出call
val i = readyAsyncCalls.iterator() ③
while (i.hasNext()) {
val asyncCall = i.next()
if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.
i.remove()
asyncCall.callsPerHost.incrementAndGet()
executableCalls.add(asyncCall)
// 放入正在执行的队列中
runningAsyncCalls.add(asyncCall) ④
}
isRunning = runningCallsCount() > 0
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
// 执行AsyncCall.executeOn()方法
// executorService为线程池
asyncCall.executeOn(executorService) ⑤
}
return isRunning
}
@get:JvmName("executorService") val executorService: ExecutorService
get() {
if (executorServiceOrNull == null) {
executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
}
return executorServiceOrNull!!
}
这个流程我们逐一分析:
①处首先将请求方法待执行的队列中,也就是readyAsyncCalls
;
②处调用promoteAndExecute()
去做一些执行前的准备工作;
③处遍历待执行的队列readyAsyncCalls
;
④处将这些待执行的请求,添加到正在执行的队列runningAsyncCalls
中;
⑤处调用AsyncCall.executeOn(executorServicer)
方法。
这里提一下executorService
是一个核心数为0,最大线程数为Int
最大值的一个线程池,用来异步执行网络请求。
接下来我们继续进入AsyncCall.executeOn(executorServicer)
AsyncCall.executeOn()
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!
}
}
}
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()
}
}
①处转到线程池的execute(this)
方法中,接下来分析;
②处当执行结束进行到finally
中的时候去③处将此次请求从runningSyncCalls
队列中移除。
上面我们提到,最终请求是转到了ExecutorService.execute(this)
中,此时我们可以看下AsyncCall
是实现了Runnable
接口的,所以最终还是调用的AsyncCall.run()
方法,这样我们就可以去run()
中寻找接下来的流程了。
AsyncCall.run()
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
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("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 {
// 将call在runningQueue移除
client.dispatcher.finished(this)
}
}
}
}
①这里就是去真正执行网络请求的起始点,可以通过getResponseWithInterceptorChain()
拿到接口回调;
②回调网络请求结果。
重点看下getResponseWithInterceptorChain()
getResponseWithInterceptorChain()
internal fun getResponseWithInterceptorChain(): Response {
// Build a full stack of interceptors.
val interceptors = mutableListOf<Interceptor>() ①
// 添加拦截器
// interceptor可以处理干净的Request
interceptors += client.interceptors
// 重试、重定向操作
interceptors += RetryAndFollowUpInterceptor(client)
// 帮我们补充数据,比如content_length,根据body计算大小
interceptors += BridgeInterceptor(client.cookieJar)
// 用来处理缓存,是否可以使用缓存数据等
interceptors += CacheInterceptor(client.cache)
// 去和服务器建立连接,这里包括了三次握手
interceptors += ConnectInterceptor
if (!forWebSocket) {
// networkInterceptors是经过重试重定向、桥接、缓存、连接拦截之后的Request,一般不推荐
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 {
// 执行拦截器得到最终的Response
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)
}
}
}
①处这里添加请求拦截器:
client.interceptors
是我们通过OkHttpClient.Builder().addInterceptor()
添加的自定义拦截器,需要注意的是,这里的Request
是最干净的请求,没有被其它拦截器进行修改,一般我们可以添加日志信息打印拦截器、公共头参拦截器等;RetryAndFollowUpInterceptor
用来重试、重定向操作的一个拦截器;BridgeInterceptor
这个拦截器主要就是帮助我们补充一些请求信息,比如:conten_length,requestBody大小等信息;CacheInterceptor
用来处理缓存,是否可以使用缓存数据等;ConnectInterceptor
去和服务器建立连接,这里包括了三次握手;client.networkInterceptors
是我们通过OkHttpClient.Builder().addNetworkInterceptor()
添加的自定义网络拦截器,这里我们可以出来,它的调用前面已经经历了一些重定向、桥接、缓存拦截器,并不是原始的Request
;CallServerInterceptor
真正去执行内容请求的拦截器。
关于拦截器是如何工作的,我会再后续文章详细介绍,这里就不深入探讨了。
②处创建了一个RealInterceptorChain
对象,记住一个信息index = 0
,它是后续拦截器责任链工作的重点因素之一;
③调用了RealInterceptorChain.proceed()
方法,开启责任链。
RealInterceptorChain.proceed
override fun proceed(request: Request): Response {
check(index < interceptors.size)
calls++
// Call the next interceptor in the chain.
val next = copy(index = index + 1, request = request) ①
val interceptor = interceptors[index] ②
@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
}
①这里提前copy
下一个的Chain
对象;
②拿到当前的拦截器;
③这里调用拦截器interceptor.intercept(chain)
方法,在这个方法里面,会依次调用chain.proceed()
方法,直到最后一个拦截器,然后将结果返回。
拦截器的责任链模式流程大致如下图所示:
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
最后针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
需要资料的朋友可以扫描下方二维码