上一次讲到,OkHttp无论是同步请求还是异步请求,最后的结果都是返回getResponseWithInterceptorChain() ,它是RealCall类里的一个方法,实际上就是请求通过由若干个拦截器组成的拦截链返回的Response对象。
getResponseWithInterceptorChain()
@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)
}
}
}
建立一个完整的拦截器堆栈,由5个拦截器组成:
1.RetryAndFollowUpInterceptor(重试并重定向拦截器)
2.BridgeInterceptor(桥梁拦截器)
3.CacheInterceptor(缓存拦截器)
4.ConnectInterceptor(连接拦截器)
5.CallServerInterceptor(呼叫服务器拦截器)
将拦截器堆栈interceptors,转换成拦截链chain
val response = chain.proceed(originalRequest)
我们来看proceed方法
前四个拦截器都会去调用proceed方法,加上getResponseWithInterceptorChain()调用一次,就调用了5次proceed方法,然后通过copy方法来调用下一个拦截器,其中index+1
我们发现copy方法中又new了一个RealInterceptorChain对象,可以用递归的思想来理解
最后将拦截对象传递给拦截器得到response
注意!!!
拦截器通常是先对request进行处理,再调用proceed方法,然后对response进行处理。
可以理解为以proceed方法为分割线。
这也就是我们通常说的责任链模式,依次执行拦截器1对request处理部分,然后传递给拦截器2对request处理部分,传递给最后一个拦截器即第n个,然后由第n个传回第n-1个处理response,直到传回第一个。
不仅okhttp自带有拦截器,我们也可以自行添加拦截器。我们添加的拦截器在okhttp原有拦截器之前,比如我们先添加日志拦截器1,再添加日志拦截器2,执行日志拦截器1对request处理部分,再执行日志拦截器2对request处理部分,再执行okhttp自带的拦截器,最后先传回给日志拦截器2对response处理部分,再传给日志拦截器1对response处理部分,因为日志拦截器基本都是对response进行日志打印,所以日志拦截器2的日志先打印出来。
总结
- OkHttp 整个请求流程是由一条拦截链完成,拦截链会用递归的方式来遍历整个拦截器列表,直到最后一个拦截器才停止递归,等所有的拦截器遍历完了网络请求也就结束了,然后由拦截链返回最终的请求结果。