一个网络请求的流程框架?想了解 enqueue 怎么进行异步请求的
1 okhttpClient.newCall(request) 返回的是一个 RealCall 对象
2 然后执行realCall.enqueue 实际里边调用的是 dispatcher .enqueue 将网络请求放到后台线程执行
3 在后台线程 通过 getResponseWithInterceptorChain() 获取返回的响应response 放在callback 里回调回来
简单使用:
var okhttpClient: OkHttpClient = OkHttpClient();
var request: Request = Request.Builder()
.url("https://square.github.io/okhttp/")
.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")
}
})
1 寻找切入点 enqueue 是个 call接口里的抽象方法 那么 返回来 看newCall怎么创建的 点击进去 newCall 进入了
OkHttpClient.kt
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
newCall 是创建 一个 RealCall对象 继续看 RealCall.的 enqueue
RealCall 里维系了几个参数
参数1 OkHttpClient 就是上边创建的OkHttpClient 通用配置都在这个类里 【比如超时时间啊什么的】
参数 2 Request originalRequest 请求 就是上边创建的请求,用来发起一个http请求 的条件 请求方法啊 http还是https什么的
这里有个 originalRequest 初始的request ,什么是初始request ,我们用来网络请求的request 不是最初传入的这个原始的request的 而是进过封装改变后的request ,最初被传入的就是这个初始的request
参数3 final boolean forWebSocket; WebSocket也像http也是 应用层协议,,一般用不到 看看就行,,,适用频繁刷新数据 如股票软件
2 RealCall.kt 是Call 接口的实现 看RealCall 里enqueue 就可以 异步的网络请求
override fun enqueue(responseCallback: Callback) {
check(executed.compareAndSet(false, true)) { "Already Executed" }
callStart()
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
2.1看 callStart方法 :作用 对http交互过程中进行监听的
private fun callStart() {
// 跟踪程序的错误 在出错的时候 做错误分析用的
this.callStackTrace = Platform.get().getStackTraceForCloseable("response.body().close()")
// eventListener 是对http交互过程的监听器 比如http header body开始发送,header body开始接收 链接的建立啊 都会监听,而这里是callStart
eventListener.callStart(this)
}
2.2 看 client.dispatcher.enqueue(AsyncCall(responseCallback)) 方法 里 dispatcher 是什么 dispatcher .enqueue方法干了什么AsyncCall是什么
追溯 dispatcher 发现 他是 Dispatcher的一个类 ,,这个 Dispatcher 实际上是做线程调度的,比如网络请求 同一时间 可能会有多个请求,,多个线程的管理 就需要线程调度,看Dispatcher里边实际上用的还是 Java里的ExecutorService 多线程管理的线程池的管理
2,3看 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()
}
实际上把 call 添加到 readyAsyncCalls 里 然后执行 promoteAndExecute()方法,,这个call是参数里 AsyncCall
2.4 看 readyAsyncCalls 是什么 点击进去
// 把准备好要执行 还没执行 的call加入到这个双向队列里
private val readyAsyncCalls = ArrayDeque<AsyncCall>()
然后再promoteAndExecute()里执行掉
2.5 接下来看 promoteAndExecute ,把符合条件的call 推举处理 然后执行。。符合的条件 1 需要还没执行过在readyAsyncCalls 里的 2 执行他不会导致超负载
private fun promoteAndExecute(): Boolean {
this.assertThreadDoesntHoldLock()
val executableCalls = mutableListOf<AsyncCall>()
val isRunning: Boolean
// 1 先挑选 符合条件的call,,readyAsyncCalls.iterator() 遍历出不会超负载的call挑出来
就promote 放在 executableCalls 集合里【可以执行的】
synchronized(this) {
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)
// 把选出来的call也会放在 runningAsyncCalls 正在执行的call里
runningAsyncCalls.add(asyncCall)
}
isRunning = runningCallsCount() > 0
}
// 2 然后执行 存在这里可以执行的 call 集合 executableCalls
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
// 对每个call执行 executeOn
asyncCall.executeOn(executorService)
}
return isRunning
}
2.6 看 asyncCall.executeOn(executorService) 具体怎么执行的
fun executeOn(executorService: ExecutorService) {
client.dispatcher.assertThreadDoesntHoldLock()
var success = false
try {
// 核心的 线程调用 开始执行 把runnable扔进去 这时候 切到后台线程
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!
}
}
}
executorService.execute(this) 传入的参数是this 接受类型是runnable 那么 asyncCall应该是实现了 runnable 接口的 所以找 asyncCall的run方法就行
2.7 看 asyncCall的run方法
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
try {
// 拿到返回的响应
val response = getResponseWithInterceptorChain()
signalledCallback = true
// responseCallback就是我们在enqueue 传入的callBack
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)
}
}
}
找到了返回的响应
val response = getResponseWithInterceptorChain()
signalledCallback = true
// responseCallback就是我们在enqueue 传入的callBack
responseCallback.onResponse(this@RealCall, response)
这里 responseCallback 对应 当初传入的callBack
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")
}
})
3 看 realCall 里 execute() 同步网络请求的方法 【一般不会调用】
override fun execute(): Response {
check(executed.compareAndSet(false, true)) { "Already Executed" }
timeout.enter()
callStart()
try {
client.dispatcher.executed(this)
return getResponseWithInterceptorChain()
} finally {
client.dispatcher.finished(this)
}
}
关键代码 还是 getResponseWithInterceptorChain() 直接 返回了 Response