var okHttpClient = OkHttpClient.Builder()
.readTimeout(readTimeout.toLong(), TimeUnit.MILLISECONDS)
.connectTimeout(connectTimeOut.toLong(), TimeUnit.MILLISECONDS)
.addInterceptor(tokenInterceptor)
.addInterceptor(logInterceptor)
.addInterceptor(mRewriteCacheControlInterceptor)
.addNetworkInterceptor(mRewriteCacheControlInterceptor)
.addInterceptor(headerInterceptor)
.addInterceptor(basicParamsInterceptor)
.cache(cache)
.build()
从代码的源头OkHttpClient的声明开始看,OkHttpClient实现了Call和WebSocket两个接口内的工厂接口Factory
以及java本身的Cloneable接口
open class OkHttpClient internal constructor(
builder: Builder
) : Cloneable, Call.Factory, WebSocket.Factory {
OkHttp的内部实现用到了Builder模式。
内部类Builder持有一个MutableList,存储着接口Interceptor的实现类
class Builder constructor() {
internal val interceptors: MutableList<Interceptor> = mutableListOf()
OkHttpClient.Builder()方法创建了OkHttpClient.Builder的实例,addInterceptor(interceptor: Interceptor)传入
okhttp3.Interceptor接口类型的实现类,方法内部通过 kotlin语法中的apply {+=interceptor}将传入的interceptor添加到成员变量 interceptors的MutableList 中。
fun addInterceptor(interceptor: Interceptor) = apply {
interceptors += interceptor
}
val request = Request.Builder().url("http://www.baidu.com").build()
okHttpClient.newCall(request).execute()
Request.Builder.build()最终返回的Request类型实例
open fun build(): Request {
return Request(
checkNotNull(url) { "url == null" },
method,
headers.build(),
body,
tags.toImmutableMap()
)
}
}
HttpClient中 newCall方法的调用
/** 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)
}
OkHttpClient.newCall方法返回了Call类型的实例,看到这里应该看一下Call是什么
/**
* A call is a request that has been prepared for execution. A call can be canceled. As this object
* represents a single request/response pair (stream), it cannot be executed twice.
*/
interface Call : Cloneable {
/** Returns the original request that initiated this call. */
fun request(): Request
/**
* Invokes the request immediately, and blocks until the response can be processed or is in error.
*
* To avoid leaking resources callers should close the [Response] which in turn will close the
* underlying [ResponseBody].
*
* ```
* // ensure the response (and underlying response body) is closed
* try (Response response = client.newCall(request).execute()) {
* ...
* }
* ```
*
* The caller may read the response body with the response's [Response.body] method. To avoid
* leaking resources callers must [close the response body][ResponseBody] or the response.
*
* Note that transport-layer success (receiving a HTTP response code, headers and body) does not
* necessarily indicate application-layer success: `response` may still indicate an unhappy HTTP
* response code like 404 or 500.
*
* @throws IOException if the request could not be executed due to cancellation, a connectivity
* problem or timeout. Because networks can fail during an exchange, it is possible that the
* remote server accepted the request before the failure.
* @throws IllegalStateException when the call has already been executed.
*/
@Throws(IOException::class)
fun execute(): Response
/**
* Schedules the request to be executed at some point in the future.
*
* The [dispatcher][OkHttpClient.dispatcher] defines when the request will run: usually
* immediately unless there are several other requests currently being executed.
*
* This client will later call back `responseCallback` with either an HTTP response or a failure
* exception.
*
* @throws IllegalStateException when the call has already been executed.
*/
fun enqueue(responseCallback: Callback)
/** Cancels the request, if possible. Requests that are already complete cannot be canceled. */
fun cancel()
/**
* Returns true if this call has been either [executed][execute] or [enqueued][enqueue]. It is an
* error to execute a call more than once.
*/
fun isExecuted(): Boolean
fun isCanceled(): Boolean
/**
* Returns a timeout that spans the entire call: resolving DNS, connecting, writing the request
* body, server processing, and reading the response body. If the call requires redirects or
* retries all must complete within one timeout period.
*
* Configure the client's default timeout with [OkHttpClient.Builder.callTimeout].
*/
fun timeout(): Timeout
/**
* Create a new, identical call to this one which can be enqueued or executed even if this call
* has already been.
*/
public override fun clone(): Call
interface Factory {
fun newCall(request: Request): Call
}
}
可以看到Call是一个接口,里面有做request(),execute(),enqueue(responseCallback: Callback)等方法,
不难看出enqueue中传入了一个callback,所以enqueue应该是一个异步请求的形式,那么相对的execute()
就是同步了
companion object {
fun newRealCall(
client: OkHttpClient,
originalRequest: Request,
forWebSocket: Boolean
): RealCall {
// Safely publish the Call instance to the EventListener.
return RealCall(client, originalRequest, forWebSocket).apply {
transmitter = Transmitter(client, this)
}
}
}
那么再回头看HttpClient中的newCall()方法,Call实例真正来自RealCall类中的newRealCall()
说明HttpClient.newCall实际是生成了一个Call接口的实现类RealCall
HttpClient.newCall实际上做的是对RealCall进行初始化
internal class RealCall private constructor(
val client: OkHttpClient,
/** The application's original request unadulterated by redirects or auth headers. */
val originalRequest: Request,
val forWebSocket: Boolean
) : Call {
/**
* There is a cycle between the [Call] and [Transmitter] that makes this awkward.
* This is set after immediately after creating the call instance.
*/
private lateinit var transmitter: Transmitter
再看一下Transmitter是什么
/**
* 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.
*/
class Transmitter(
private val client: OkHttpClient,
private val call: Call
) {
transmitter
英 [trænz’mɪtə; trɑːnz-; -ns-] 美 [træns’mɪtɚ]
n. [电讯] 发射机,[通信] 发报机;传达人
结合单词的意思和注释可以知道transmitter是OkHttp中去处理连接、请求、响应和流的一个类,支持一步取消和取消
所以还得往下看Call类做了什么。
点进Call的代码中可以看到Call是一个接口
所以OkHttpClient.newCall.execute()调用的是RealCall类的execute()方法,
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)
}
}
通过方法名可知getResponseWithInterceptorChain()是真正得到响应后传给初始化的MutableList inteceptors顺序去处理的方法,现在暂时不刨根问底研究其中更深的细节,先了解一下intecepor
@Throws(IOException::class)
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(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)
}
}
}
聚焦到这段代码
val chain = RealInterceptorChain(interceptors, transmitter, null, 0, originalRequest, this,
client.connectTimeoutMillis, client.readTimeoutMillis, client.writeTimeoutMillis)
class RealInterceptorChain(
private val interceptors: List<Interceptor>,
private val transmitter: Transmitter,
private val exchange: Exchange?,
private val index: Int,
private val request: Request,
private val call: Call,
private val connectTimeout: Int,
private val readTimeout: Int,
private val writeTimeout: Int
) : Interceptor.Chain {
接着看Interceptor.Chain发现比较熟悉,
/**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding
* responses coming back in. Typically interceptors add, remove, or transform headers on the request
* or response.
*/
interface Interceptor {
@Throws(IOException::class)
fun intercept(chain: Chain): Response
companion object {
/**
* Constructs an interceptor for a lambda. This compact syntax is most useful for inline
* interceptors.
*
* ```
* val interceptor = Interceptor { chain: Interceptor.Chain ->
* chain.proceed(chain.request())
* }
* ```
*/
inline operator fun invoke(crossinline block: (chain: Chain) -> Response): Interceptor =
object : Interceptor {
override fun intercept(chain: Chain) = block(chain)
}
}
interface Chain {
fun request(): Request
@Throws(IOException::class)
fun proceed(request: Request): Response
/**
* Returns the connection the request will be executed on. This is only available in the chains
* of network interceptors; for application interceptors this is always null.
*/
fun connection(): Connection?
fun call(): Call
fun connectTimeoutMillis(): Int
fun withConnectTimeout(timeout: Int, unit: TimeUnit): Chain
fun readTimeoutMillis(): Int
fun withReadTimeout(timeout: Int, unit: TimeUnit): Chain
fun writeTimeoutMillis(): Int
fun withWriteTimeout(timeout: Int, unit: TimeUnit): Chain
}
}
不难发现RealInteceptorChain正是OkHttp请求成功后真正的InteceptorChain
@Throws(IOException::class)
fun proceed(request: Request, transmitter: Transmitter, exchange: Exchange?): Response {
if (index >= interceptors.size) throw AssertionError()
calls++
// If we already have a stream, confirm that the incoming request will use it.
check(this.exchange == null || this.exchange.connection()!!.supportsUrl(request.url)) {
"network interceptor ${interceptors[index - 1]} must retain the same host and port"
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
check(this.exchange == null || calls <= 1) {
"network interceptor ${interceptors[index - 1]} must call proceed() exactly once"
}
// Call the next interceptor in the chain.
val next = RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout)
val interceptor = interceptors[index]
@Suppress("USELESS_ELVIS")
val response = interceptor.intercept(next) ?: throw NullPointerException(
"interceptor $interceptor returned null")
// Confirm that the next interceptor made its required call to chain.proceed().
check(exchange == null || 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
}
留意到这段代码
// Call the next interceptor in the chain.
val next = RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout)
val interceptor = interceptors[index]
@Suppress("USELESS_ELVIS")
val response = interceptor.intercept(next) ?: throw NullPointerException(
"interceptor $interceptor returned null")
// Confirm that the next interceptor made its required call to chain.proceed().
check(exchange == null || index + 1 >= interceptors.size || next.calls == 1) {
"network interceptor $interceptor must call proceed() exactly once"
}
根据平时使用OkHttp interceptor的经验拦截器会根据添加的顺序依次拦截,对应的就是这几行代码,
interceptor代表当前拦截器,next为下一个拦截器链的下一环,再看一下HttpLoggingInterceptor的intercept(chain: Interceptor.Chain)方法,中间有一行代码
response = chain.proceed(request)
这段代码可以在大多数拦截器中看到,不难发现这正是Java责任链模式的一个应用场景
不难从Inteceptor接口的注释中看到端倪
/**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding
* responses coming back in. Typically interceptors add, remove, or transform headers on the request
* or response.
*/
interface Interceptor {
@Throws(IOException::class)
fun intercept(chain: Chain): Response
companion object {
/**
* Constructs an interceptor for a lambda. This compact syntax is most useful for inline
* interceptors.
*
* ```
* val interceptor = Interceptor { chain: Interceptor.Chain ->
* chain.proceed(chain.request())
* }
* ```
*/
inline operator fun invoke(crossinline block: (chain: Chain) -> Response): Interceptor =
object : Interceptor {
override fun intercept(chain: Chain) = block(chain)
}
}
所以 这行代码最后会执行chain.proceed(chain.request())
val response = interceptor.intercept(next) ?: throw NullPointerException(
"interceptor $interceptor returned null")
也就是RealInteceptor中的process(request: Request)这个方法,而这个方法调用的又是interceptor.intercept(next)
所在的方法,个人理解这是一种递归调用。直到response 被处理
override fun proceed(request: Request): Response {
return proceed(request, transmitter, exchange)
}