「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
一、使用
流程图
在使用OkHttp发起一次请求时,对于使用者最少存在OkHttpClient、Request与Call三个角色。其中OkHttpClient和Request的创建可以使用它为我们提供的Builder(建造者模式)。而Call则是把Request交给OkHttpClient之后返回的一个已准备好执行的请求
1. execute() 同步请求
一直等待http请求, 直到返回了响应. 在这之间会阻塞进程
override fun execute(): Response {
//首先判断是否已执行过,如果已经执行过,则抛出异常信息,也就是说一次Call实例只能调用一次execute()方法
check(executed.compareAndSet(false, true)) { "Already Executed" }
timeout.enter()
callStart()
try {
//如果未执行,则调用Dispatcher类的executed()方法将该Call加入到一个双端队列中
client.dispatcher.executed(this)
//调用getResponseWithInterceptorChain()方法返回Response对象
return getResponseWithInterceptorChain()
} finally {
//从已经执行的双端队列中移除本次Call
client.dispatcher.finished(this)
}
}
@Synchronized internal fun executed(call: RealCall) {
runningSyncCalls.add(call)
}
经过上面的分析,真正发出网络请求并返回结果的应该是getResponseWithInterceptorChain()方法
2. enqueuer 异步请求
在另外的工作线程中执行http请求, 请求时不会阻塞当前的线程
override fun enqueue(responseCallback: Callback) {
//首先校验这个Call是否已经被执行,如果执行过,就报异常
check(executed.compareAndSet(false, true)) { "Already Executed" }
callStart()
//调用Dispatcher分发器的enqueue()方法
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
AsyncCall是一个Runnable,在run()方法中调用了getResponseWithInterceptorChain()
inner class AsyncCall(private val responseCallback: Callback) : Runnable {
. . .
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
. . .
try {
val response = getResponseWithInterceptorChain()
signalledCallback = true
responseCallback.onResponse(this@RealCall, response)
} catch (e: IOException) {
. . .
} finally {
client.dispatcher.finished(this)
}
}
}
}
一、核心原理分析
okHttp核心流程就是分发器(Dispatcher)和拦截器(Interceptors)
1. Dispatcher
Dispatcher用于执行网络请求任务,有4个核心成员对象: ExecutorService:线程池,用于执行异步任务 Deque:有三个队列(正在执行的同步任务、正在执行的异步任务、准备执行的异步任务)
2. Interceptors
okHttp最核心的工作就是在getResponseWithInterceptorChain()中 默认情况下有五大拦截器
-
RetryAndFollowUpInterceptor:是第一个接触到请求,最后接触到响应,负责判断是否需要重新发起整个请求
重试的前提是出现了RouteException或者IOException,一旦在后续的拦截器中执行过程中出现这两个异常,就会通过recover方法进行判断是否进行连接重试 重定向发生在重试的判断之后,如果不满足重试条件,还需要进一步调用followUpRequest,根据Response的响应码(如果请求失败,Response都不存在就会抛出异常) -
BridgeInterceptor:补全请求,并对响应进行额外处理
连接应用程序和服务器的桥梁,发出的请求将会经过它的处理才能发给服务器,比如设置内容长度,编码,gzip压缩,cookie等,获取响应后保存Cookie等操作 对用户构建的Request进行添加或者删除相关头部信息,以转化成能够真正进行网络请求的Request,将符合网络请求规范的Request交给下一个拦截器处理,并获取Response 如果响应体经过了GZIP压缩,那就需要解压,再构建成用户可用的Response并返回 -
CacheInterceptor:请求前查询缓存,获得响应并判断是否需要缓存
在发出请求前,判断是否命中缓存。如果命中则可以不请求,直接使用缓存的响应。 (只会存在Get请求的缓存) 步骤: 从缓存中获取对应请求的响应缓存 创建CacheStrategy,创建时会判断是否能够使用缓存,在CacheStrategy中存在两个成员:netWorkRequest与cacheResponse -
networkInterceptors:与服务器完成TCP连接
打开与目标服务器的连接,并执行下一个拦截器 -
CallServerInterceptor:与服务器进行通信,封装请求数据与解析响应数据
利用HttpCodec发出请求道服务器并解析生成Response