Android 访问网络的框架从一开始的 HttpClient 和 HttpUrlConnection,再到 Volley 等,直到现在已经是 OkHttp + Retrofit 的结合。OkHttp 会成为一种流行的网络请求框架,肯定有它的特点,此篇文章将梳理 OkHttp 的源码,对于 Retrofit 将在其他后续进行分析。
OkHttp 请求网络的方式如下所示,以下将根据这个流程进行分析。
//1.创建一个 Request
val request = Request.Builder().url(url)
.method("GET", null)
.build()
//2.创建一个 Client
val okHttpClient = OkHttpClient.Builder().build()
//3.得到一个 Call
val call = okHttpClient.newCall(request)
//4.1.异步请求
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
}
override fun onResponse(call: Call, response: Response) {
val result = response.body?.string()
if (result != null) {
Log.d("result", result)
}
}
})
在 Request 的 Builder 类中定义了几个参数:
open class Builder {
internal var url: HttpUrl? = null
internal var method: String
internal var headers: Headers.Builder
internal var body: RequestBody? = null
...
open fun url(url: HttpUrl): Builder = apply {
this.url = url
}
...
open fun method(method: String, body: RequestBody?): Builder = apply {
require(method.isNotEmpty()) {
"method.isEmpty() == true"
}
if (body == null) {
require(!HttpMethod.requiresRequestBody(method)) {
"method $method must have a request body."
}
} else {
require(HttpMethod.permitsRequestBody(method)) {
"method $method must not have a request body."
}
}
this.method = method
this.body = body
}
...
}
可以看到通过调用 Builder() 的 url() 和 method() 方法是给 Builder 类中的参数进行赋值,最终返回的都是 Builder 类型,最后调用了 build() 方法去构建一个 Request 对象:
open fun build(): Request {
return Request(
checkNotNull(url) { "url == null" },
method,
headers.build(),
body,
tags.toImmutableMap()
)
}
val okHttpClient = OkHttpClient.Builder().build()
在构建 OkHttpClient 同样调用的是其内部类 Builder:
class Builder constructor() {
internal var dispatcher: Dispatcher = Dispatcher()
internal var connectionPool: ConnectionPool = ConnectionPool()
internal val interceptors: MutableList = mutableListOf()
internal val networkInterceptors: MutableList = mutableListOf()
internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()
internal var retryOnConnectionFailure = true
internal var authenticator: Authenticator = Authenticator.NONE
internal var followRedirects = true
internal var followSslRedirects = true
internal var cookieJar: CookieJar = CookieJar.NO_COOKIES
internal var cache: Cache? = null
internal var dns: Dns = Dns.SYSTEM
internal var proxy: Proxy? = null
internal var proxySelector: ProxySelector? = null
internal var proxyAuthenticator: Authenticator = Authenticator.NONE
internal var socketFactory: SocketFactory = SocketFactory.getDefault()
internal var sslSocketFactoryOrNull: SSLSocketFactory? = null
internal var x509TrustManagerOrNull: X509TrustManager? = null
internal var connectionSpecs: List = DEFAULT_CONNECTION_SPECS
internal var protocols: List = DEFAULT_PROTOCOLS
internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier
internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT
internal var certificateChainCleaner: CertificateChainCleaner? = null
internal var callTimeout = 0
internal var connectTimeout = 10_000
internal var readTimeout = 10_000
internal var writeTimeout = 10_000
internal var pingInterval = 0
internal var minWebSocketMessageToCompress = RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE
internal var routeDatabase: RouteDatabase? = null
...
internal constructor(okHttpClient: OkHttpClient) : this() {
this.dispatcher = okHttpClient.dispatcher
this.connectionPool = okHttpClient.connectionPool
this.interceptors += okHttpClient.interceptors
this.networkInterceptors += okHttpClient.networkInterceptors
this.eventListenerFactory = okHttpClient.eventListenerFactory
this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure
this.authenticator = okHttpClient.authenticator
this.followRedirects = okHttpClient.followRedirects
this.followSslRedirects = okHttpClient.followSslRedirects
this.cookieJar = okHttpClient.cookieJar
this.cache = okHttpClient.cache
this.dns = okHttpClient.dns
this.proxy = okHttpClient.proxy
this.proxySelector = okHttpClient.proxySelector
this.proxyAuthenticator = okHttpClient.proxyAuthenticator
this.socketFactory = okHttpClient.socketFactory
this.sslSocketFactoryOrNull = okHttpClient.sslSocketFactoryOrNull
this.x509TrustManagerOrNull = okHttpClient.x509TrustManager
this.connectionSpecs = okHttpClient.connectionSpecs
this.protocols = okHttpClient.protocols
this.hostnameVerifier = okHttpClient.hostnameVerifier
this.certificatePinner = okHttpClient.certificatePinner
this.certificateChainCleaner = okHttpClient.certificateChainCleaner
this.callTimeout = okHttpClient.callTimeoutMillis
this.connectTimeout = okHttpClient.connectTimeoutMillis
this.readTimeout = okHttpClient.readTimeoutMillis
this.writeTimeout = okHttpClient.writeTimeoutMillis
this.pingInterval = okHttpClient.pingIntervalMillis
this.minWebSocketMessageToCompress = okHttpClient.minWebSocketMessageToCompress
this.routeDatabase = okHttpClient.routeDatabase
}
}
在 OkHttp 的内部类 Builder 中对相关变量进行初始化。接着调用了 build() 方法:
fun build(): OkHttpClient = OkHttpClient(this)
在 build() 方法中构建了 OkHttp 变量。
val call = okHttpClient.newCall(request)
通过调用 okHttpClient 的 newCall(request) 方法:
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
Call 是一个接口:
interface Call : Cloneable {
/** Returns the original request that initiated this call. */
fun request(): Request
@Throws(IOException::class)
fun execute(): Response
fun enqueue(responseCallback: Callback)
fun cancel()
fun isExecuted(): Boolean
fun isCanceled(): Boolean
fun timeout(): Timeout
public override fun clone(): Call
interface Factory {
fun newCall(request: Request): Call
}
}
而它的实现类是 RealCall
class RealCall(
val client: OkHttpClient,
/** The application's original request unadulterated by redirects or auth headers. */
val originalRequest: Request,
val forWebSocket: Boolean
) : Call {
...
}
RealCall 请求方式分为两种:同步请求(execute) 和 异步请求(enqueue)。
调用了 RealCall 的 enqueue 方法进行异步请求:
override fun enqueue(responseCallback: Callback) {
synchronized(this) {
check(!executed) { "Already Executed" }
executed = true
}
callStart()
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
这里的核心是最后一句代码的执行,先看括号中创建的 AsyncCall(responseCallback):
internal inner class AsyncCall(
private val responseCallback: Callback
) : Runnable {
...
}
AsyncCall 继承 Runnable,这里暂时不分析 AsyncCall 如何执行。先继续看 client.dispatcher.enqueue() 方法。
Dispatcher 是在 OkHttpClient 的内部类 Builder 中进行初始化。在 Dispatcher 中定义了默认最大请求数和每个主机最大请求数:
var maxRequests = 64 // 最大请求数
var maxRequestsPerHost = 5 // 每个主机最大请求数
以及两个队列,将要执行的队列、正在执行的异步队列和正在执行的同步队列:
/** Ready async calls in the order they'll be run. */
private val readyAsyncCalls = ArrayDeque()
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private val runningAsyncCalls = ArrayDeque()
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private val runningSyncCalls = ArrayDeque()
接着调用了 Dispatcher 的 enqueue() 方法:
class Dispatcher constructor() {
...
internal fun enqueue(call: AsyncCall) {
synchronized(this) {
readyAsyncCalls.add(call)
if (!call.call.forWebSocket) {
val existingCall = findExistingCallWithHost(call.host)
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
}
}
promoteAndExecute()
}
...
}
将 AsyncCall 类型的 call 添加进将要执行的队列中,接着看 promoteAndExecute() 方法:
private fun promoteAndExecute(): Boolean {
this.assertThreadDoesntHoldLock()
val executableCalls = mutableListOf()
val isRunning: Boolean
synchronized(this) {
val i = readyAsyncCalls.iterator()
while (i.hasNext()) {
val asyncCall = i.next()
if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
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
}
定义一个可执行的列表 executableCalls ,通过遍历将要执行的队列,并将其添加进去可执行的列表和运行中的队列中。接着遍历可执行的列表,并执行 asyncCall.executeOn(executorService) 方法,executorService 是一个线程池。
AsyncCall 是 RealCall 的一个内部类,并且继承 Runnable:
internal inner class AsyncCall(
private val responseCallback: Callback
) : Runnable {
...
}
在上一步中调用了 executeOn(executorService) 方法,并将线程池传递进 AsyncCall 中:
fun executeOn(executorService: ExecutorService) {
client.dispatcher.assertThreadDoesntHoldLock()
var success = false
try {
executorService.execute(this)
success = true
} catch (e: RejectedExecutionException) {
val ioException = InterruptedIOException("executor rejected")
ioException.initCause(e)
noMoreExchanges(ioException)
responseCallback.onFailure(this@RealCall, ioException)
} finally {
if (!success) {
client.dispatcher.finished(this) // This call is no longer running!
}
}
}
通过调用 executorService.execute(this) 执行线程,这里会执行到 AsyncCall 的 run 方法,如果出现异常,调到 catch方法中,则调用 responseCallback.onFailure,最后,执行失败,则调用 Dispatch 的 finish() 方法。
先看 run 方法:
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
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("Callback failure for ${toLoggableString()}", Platform.INFO, e)
} else {
responseCallback.onFailure(this@RealCall, e)
}
} catch (t: Throwable) {
cancel()
if (!signalledCallback) {
val canceledException = IOException("canceled due to $t")
canceledException.addSuppressed(t)
responseCallback.onFailure(this@RealCall, canceledException)
}
throw t
} finally {
client.dispatcher.finished(this)
}
}
}
在 run 方法中的核心是以下代码,最终执行完毕都会调用 Dispatch 的 finish() 方法:
val response = getResponseWithInterceptorChain()
signalledCallback = true
responseCallback.onResponse(this@RealCall, response)
通过 getResponseWithInterceptorChain() 方法获取返回响应,并通过回调调用了 onResponse() 方法,将返回响应传递出去。
getResponseWithInterceptorChain 方法:
@Throws(IOException::class)
internal fun getResponseWithInterceptorChain(): Response {
// Build a full stack of interceptors.
val interceptors = mutableListOf()
interceptors += client.interceptors //添加自定义的拦截器,自定义拦截器会被优先处理
interceptors += RetryAndFollowUpInterceptor(client) //添加重试和重定向拦截器
interceptors += BridgeInterceptor(client.cookieJar) //添加转换桥拦截器
interceptors += CacheInterceptor(client.cache) //添加缓存拦截器
interceptors += ConnectInterceptor //添加链接拦截器
if (!forWebSocket) {
interceptors += client.networkInterceptors //不是websocket添加网络拦截器
}
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)
}
}
}
此方法中添加一系列的拦截器,并构建拦截器链,并执行 proceed() 方法得到返回响应。
Interceptor 是一个接口,默认存在五种类型的拦截器,它们都是 Interceptor 的实现类:
RetryAndFollowUpInterceptor: 负责失败重试以及重定向的拦截器;
BridgeInterceptor: 负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转为用户友好的响应的;
CacheInterceptor: 负责读取缓存直接返回、更新缓存;
ConnectInterceptor: 负责和服务器建立连接的;
CallServerInterceptor:负责向服务器发送请求数据、从服务器读取响应数据;
构建拦截器链的类为 RealInterceptorChain,RealInterceptorChain 的父类是 Interceptor.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
}
RealInterceptorChain 类:
class RealInterceptorChain(
internal val call: RealCall,
private val interceptors: List,
private val index: Int,
internal val exchange: Exchange?,
internal val request: Request,
internal val connectTimeoutMillis: Int,
internal val readTimeoutMillis: Int,
internal val writeTimeoutMillis: Int
) : Interceptor.Chain {
...
}
在上面的流程中执行了 proceed() 方法:
@Throws(IOException::class)
override fun proceed(request: Request): Response {
...
// 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")
...
return response
}
OkHttp 就是通过定义许多拦截器一步一步地对 Request 进行拦截处理(从头至尾),直到请求返回网络数据,后面又倒过来,一步一步地对 Response 进行拦截处理,最后拦截的结果就是回调的最终 Response。
通过 Request 的内部类 Builder 定义相关变量,并通过 url() 等方法对相关变量进行赋值,通过 build() 方法构建 Request 对象。在 OkHttpClient 的内部类 Builder 中对相关变量进行初始化,在 build() 方法中构建了 OkHttpClient 变量。 通过调用 okHttpClient 的 newCall(request) 方法,将 request 作为参数传递进去,创建一个 Call 对象。Call 是一个接口,它的实现类是 RealCall。RealCall 是对请求的封装,调用了 RealCall 的 enqueue 方法进行异步请求。Dispatcher 是在 OkHttpClient 的内部类 Builder 中进行初始化,在 Dispatcher 中定义了最大请求数为 64 和每个主机最大请求数 5。以及定义了三个队列,用于存储准备执行任务的队列、用于存储正在执行异步任务的队列和用于存储正在执行的同步任务的队列。AsyncCall 是一个 Runnable,调用了 executeOn(executorService),将线程池传递进去。executeOn 方法中通过线程池启动线程,执行 run 方法。run 方法中添加一系列的拦截器,得到拦截器链,并调用了process 方法,通过定义许多拦截器一步一步地对 Request 进行拦截处理(从头至尾),直到请求返回网络数据,后面又倒过来,一步一步地对 Response 进行拦截处理,最后拦截的结果就是回调的最终 Response。