OkHttp作为常用的网络通讯组件,其中大部分的功能点需要我们深入了解,本系列的文章将以源码角度解析组件背后的运行原理,避免踩坑。
文章中提到的okHttp版本为4.10.0,源码的git分支是4.10.x,源码git地址:https://square.github.io/okhttp/
文章概要
前面的文章我们了解了连接和连接池。这篇文章我们将深入扒一扒同步请求和异步请求的区别。
首先看下两者请求的区别
同步请求
httpClient.newCall(request).execute();
异步请求
Callback responseCallback;
httpClient.newCall(request).enqueue(responseCallback);
responseCallback.get();
首先从异步请求开始看,从enqueue方法的入参看出,请求结果通过这个类触发回调。
interface Callback {
/**
* 调用失败时
*/
fun onFailure(call: Call, e: IOException)
/**
* 调用成功时
*/
fun onResponse(call: Call, response: Response)
}
而enqueue方法构建了一个AsyncCall对象
override fun enqueue(responseCallback: Callback) {
/// 省略部分代码
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
AsyncCall类实现了Runnable接口
internal inner class AsyncCall(
private val responseCallback: Callback
)
异步请求的流程:
- 构建一个AsyncCall对象,通过Dispatcher.kt#enqueue()放入调度池中,放入调度池第一件事是从其他的待执行的请求中共享相同host的请求数量。
- 触发调度池发起调度,调度池会从readyAsyncCalls捞取一个请求,如果当前没有超过最大请求量和同host最大请求量,这个请求将开始执行。
- 这个任务会被提交到Distpatcher默认executorService(无界线程池)中执行。
同步请求流程就非常简单了、省去了调度流程:
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)
}
}
总结
okhttp同步请求和异步请求的差异: 1、异步请求等待线程池调度、同步请求直接发起。2、异步请求调度有同host连接数限制、最大请求数量限制 3、异步请求通过实现传入一个Callback接口实现获取结果。
后面我们将深入分析OkHttp 4.10.0版本的事件,感兴趣的同学欢迎继续关注!
-END-
本文暂时没有评论,来添加一个吧(●'◡'●)