略解Okhttp
使用
val okHttpClient = OkHttpClient()
val request = Request.Builder().url("www.baidu.com").build()
val response = okHttpClient.newCall(request).execute()
response.body?.string()
...
流程
- 创建OkHttpClient对象
- 创建Request对象
- 同步/异步请求
创建OkHttpClient对象
创建Request对象
Request对象的创建由建造者完成,默认的方法是GET,headers为空。
接着调用url方法,url方法作用是把url转换成http:..或https:…形式的字符串,用字符串创建HttpUrl对象。HttpUrl对象是把Url里的域名、端口、位置(#ToASCII)等信息以每个变量的形式单独存储。再然后用上边的值作为属性,创建Request对象。Request对象与HttpUrl相比多了body、method、headers这些值。
Request与HttpUrl的作用相似,作为请求的一部分。只不过包含了更多了请求信息。
创建RealCall对象
源码中对RealCall类的介绍:
/**
* Bridge between OkHttp's application and network layers. This class exposes high-level application
* layer primitives: connections, requests, responses, and streams.
*
* This class supports [asynchronous canceling][cancel]. This is intended to have the smallest
* blast radius possible. If an HTTP/2 stream is active, canceling will cancel that stream but not
* the other streams sharing its connection. But if the TLS handshake is still in progress then
* canceling may break the entire connection.
*/
RealCall才是真正用来请求的类。
其中execute()为同步请求的方法入口,enqueue()为异步请求的方法入口。
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)
}
}
client.dispatcher.executed(this)里。
/** Used by [Call.execute] to signal it is in-flight. */
@Synchronized internal fun executed(call: RealCall) {
runningSyncCalls.add(call)
}
再看
/** Ready async calls in the order they'll be run. */
private val readyAsyncCalls = ArrayDeque<AsyncCall>()
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private val runningAsyncCalls = ArrayDeque<AsyncCall>()
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private val runningSyncCalls = ArrayDeque<RealCall>()
上边只是把当前的Call放到Liist队列中,RealCallexecute()的方法需要返回值,真正的执行肯定是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)
}
}
}
把所有的拦截器加到一个队列,第一个拦截器是提供的自定义的拦截器,可以实现接口写一个。
构造一个RealInterceptorChain对象,返回了proceed(..)方法的结果。
@Throws(IOException::class)
override fun proceed(request: Request): Response {
check(index < interceptors.size)
calls++
if (exchange != null) {
check(exchange.finder.sameHostAndPort(request.url)){
"network interceptor ${interceptors[index - 1]} must retain the same host and port"
}
check(calls == 1){
"network interceptor ${interceptors[index - 1]} must call proceed() exactly once"
}
}
// Call the next interceptor in the chain.
val next = copy(index = index + 1, request = request)
val interceptor = interceptors[index]
@Suppress("USELESS_ELVIS")
val response = interceptor.intercept(next) ?: throw NullPointerException(
"interceptor $interceptor returned null")
if (exchange != null) {
check(index + 1 >= interceptors.size || next.calls == 1){
"network interceptor $interceptor must call proceed() exactly once"
}
}
check(response.body != null){"interceptor $interceptor returned a response with no body"}
return response
}
请求时能不断调用下一个拦截器是因为在拦截器里不拦截时,又调用到RealInterceptorChain的proceed(..)里。而
// Call the next interceptor in the chain.
val next = copy(index = index + 1, request = request)
val interceptor = interceptors[index]
copy(..)里传入是的index+1,相当于每调用一次,index+1。
最后在RealCall修改状态:
private fun <T> finished(calls: Deque<T>, call: T) {
val idleCallback: Runnable?
synchronized(this){
if (!calls.remove(call)) throw AssertionError("Call wasn't in-flight!")
idleCallback = this.idleCallback
}
val isRunning = promoteAndExecute()
if (!isRunning && idleCallback != null) {
idleCallback.run()
}
}
异步执行与同步前部分相似
异步的入口是enqueue()。源码:
override fun enqueue(responseCallback: Callback) {
check(executed.compareAndSet(false, true)){"Already Executed"}
callStart()
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
AsyncCall是RealCall的内部类,实现了Runnable接口。持有外部类的引用,在调用
拦截器
Interceptor | 作用 |
---|---|
RetryAndFollowUpInterceptor | 重试、重定向 |
BridgeInterceptor | 添加header,包括压缩格式、cookie、Content-Type |
CacheInterceptor | 判断是否可以用缓存过的响应 |
ConnectInterceptor | 建立连接,找不到时创建Socket、DNS、TCP握手 |
CallServerInterceptor | 用okio传输header和body |