Okhttp已经用了好几年了,一直也没去研究下它的流程是怎么样,内部究竟是怎么样工作的,最近研究了下,写篇博客记录下,写的不是很好。
首先先从用法开始。
- 第一步:创建OkhttpClient
val client = OkHttpClient.Builder()
//创建Client同时可以添加拦截器、指定超时时间、证书校验等等操作
.build()
- 创建Request对象
//可以在这里自定请求的ip、指定请求方式。、添加请求头
val request= Request.Builder().url("")
.post()
.get()
.addHeader()
.build()
- 异步或者同步方式去发送请求
//同步方法
val response=client.newCall(request).execute()
//异步方法
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
}
override fun onResponse(call: Call, response: Response) {
}
})
这样基本就完成了一次请求,下面来深入源码了解下每步的细节,
首先创建OkHttpClinet过程用到了建造者模式,添加拦截器等操作,这里没什么好说的
接着看创建Request的源码,同样也用到了建造者模式,指定请求地址、请求头什么的,也没什么好说的。
重点来了
- 同步请求 调用
client.newCall()
拿到Call
对象然后调用execute()
方法
/** Prepares the [request] to be executed at some point in the future. */
override fun newCall(request: Request): Call {
return RealCall.newRealCall(this, request, forWebSocket = false)
}
这里看到真正干活的是RealCall这个对象 在跟进一下
//RealCall.class
override fun execute(): Response {
synchronized(this) {
check(!executed) { "Already Executed" }
executed = true
}
transmitter.timeoutEnter()
transmitter.callStart()
try {
client.dispatcher.executed(this)
return getResponseWithInterceptorChain()
} finally {
client.dispatcher.finished(this)
}
}
这个方法返回Response对象,return 的是getResponseWithInterceptorChain()方法 在跟进下
@Throws(IOException::class)
fun getResponseWithInterceptorChain(): Response {
// 在这里添加五大拦截器
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(interceptors, transmitter, null, 0, originalRequest, this,
client.connectTimeoutMillis, client.readTimeoutMillis, client.writeTimeoutMillis)
var calledNoMoreExchanges = false
try {
//这里就是真正去执行网络请求的地方
val response = chain.proceed(originalRequest)
if (transmitter.isCanceled) {
response.closeQuietly()
throw IOException("Canceled")
}
return response
} catch (e: IOException) {
calledNoMoreExchanges = true
throw transmitter.noMoreExchanges(e) as Throwable
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null)
}
}
}
差不多到这里 整个同步请求算是完成了。同步请求看上去很简单,在梳理下流程
创建client -> 创建Request -> client.newCall(request).excute() -> RealCall.excute() -> getResponseWithInterceptorChain()
-> 拿到响应
- 异步方法 跟同步前几步一样 我们直接来看
equeue()
方法
override fun enqueue(responseCallback: Callback) {
synchronized(this) {
check(!executed) { "Already Executed" }
executed = true
}
transmitter.callStart()
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
判断是否已经执行 没有的话调用client.dispatcher.enqueue(AsyncCall(responseCallback))
这里的AsyncCall
是个Runable
我们来看看他的run方法
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
transmitter.timeoutEnter()
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(INFO, "Callback failure for ${toLoggableString()}", e)
} else {
responseCallback.onFailure(this@RealCall, e)
}
} finally {
client.dispatcher.finished(this)
}
}
}
同样也去调用了getResponseWithInterceptorChain()
这里就不跟进了,我们来看看 client.dispatcher.enqueue()
干了些撒
internal fun enqueue(call: AsyncCall) {
synchronized(this) {
//这里将异步操作放入到集合中
readyAsyncCalls.add(call)
........
promoteAndExecute()
}
这里没撒 再来看看 promoteAndExecute()
private fun promoteAndExecute(): Boolean {
assert(!Thread.holdsLock(this))
//可以执行的集合 应该叫队列吧
val executableCalls = mutableListOf<AsyncCall>()
val isRunning: Boolean
synchronized(this) {
val i = readyAsyncCalls.iterator()
//不断的从集合取任务
while (i.hasNext()) {
val asyncCall = i.next()
判断是否达到了最大请求数量 maxRequests = 64
if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
//是否达到同时执行的最大数 maxRequestsPerHost = 5
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)
}
return isRunning
}
我们在跟进下asyncCall.executeOn(executorService)
//ExecutorService是线程池
fun executeOn(executorService: ExecutorService) {
assert(!Thread.holdsLock(client.dispatcher))
var success = false
try {
//加到线程池里执行
executorService.execute(this)
success = true
} catch (e: RejectedExecutionException) {
val ioException = InterruptedIOException("executor rejected")
ioException.initCause(e)
transmitter.noMoreExchanges(ioException)
responseCallback.onFailure(this@RealCall, ioException)
} finally {
if (!success) {
client.dispatcher.finished(this) // This call is no longer running!
}
}
}
到此异步请求过程也完了,梳理下流程
创建client -> 创建Request -> client.newCall(request).equeue(callbaclk) -> RealCall.enqueue() -> client.dispatcher.enqueue(AsyncCall)往队列里添加AsyncCall -> 判断是否到达线程池最大数量 -> 加入线程池执行 -> getResponseWithInterceptorChain() -> 以Callback形式回调回去
接下来看下拦截器的原理
拦截器在getResponseWithInterceptorChain()
里添加到一个集合中,
@Throws(IOException::class)
fun getResponseWithInterceptorChain(): Response {
....
//关键1 interceptors是拦截器集合
val chain = RealInterceptorChain(interceptors, transmitter, null, 0, originalRequest, this,
client.connectTimeoutMillis, client.readTimeoutMillis, client.writeTimeoutMillis)
//关键2
val response = chain.proceed(originalRequest)
.....
return response
}
在getResponseWithInterceptorChain()
方法中生成一个链,看方法的名称可以猜到chain是拦截器的链
创建链后调用了chain.proceed(originalRequest)
跟进一下这个方法
override fun proceed(request: Request): Response {
return proceed(request, transmitter, exchange)
}
@Throws(IOException::class)
fun proceed(request: Request, transmitter: Transmitter, exchange: Exchange?): Response {
if (index >= interceptors.size) throw AssertionError()
calls++
.......省略
// Call the next interceptor in the chain. 关键
val next = RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout)
//index是上一个拦截器构造方法传进来的 +1就是调链的下一个
val interceptor = interceptors[index]
//执行一个拦截器
@Suppress("USELESS_ELVIS")
val response = interceptor.intercept(next) ?: throw NullPointerException(
"interceptor $interceptor returned null")
.......省略
return response
}
在类的方法里有new了自己 然后在interceptor.intercept(next)
怎么感觉在递归呢? 是不是一下子明白了?其实就是递归,这种写法我看了好几遍才看懂 哈哈 还是不懂?再来看段代码,随便找个拦截器 ,就拿ConnectInterceptor
代码少的把
/** Opens a connection to the target server and proceeds to the next interceptor. */
object ConnectInterceptor : Interceptor {
//假如这里的chain是 interceptor.intercept(next) 的next
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
....省略
//看这里 又去掉了proceed方法???还不懂?
//每个拦截器都有这个方法,就算自定义拦截器最后也是要 return chain.proceed(request)
return realChain.proceed(request, transmitter, exchange)
}
}
还不懂吗?哈哈。不懂在好好思虑下,。我先把流程整理下
RealInterceptorChain.proceed() -> Interceptor.intercept() -> RealInterceptorChain.proceed() -> Interceptor.intercept() -> 以此类推
在执行请求前递归执行了所有的拦截器,用到责任链设计模式
五大拦截器作用 就不去深究了源码了,大概了解下
- RetryAndFollowUpInterceptor:重试拦截器 重试机制 重定向
- BridgeInterceptor:桥接拦截器 基础的操作,比如添加cookie、Content-type、Content-Length
- CacheInterceptor:缓存拦截器 顾名思义做缓存的
- ConnectInterceptor:连接的拦截器 内部封了Socket的连接池 同一个主机不断开连接
- CallServerInterceptor(读写拦截器) 读写数据流 数据流操作