一、okhttp简单使用:
var client:OkHttpClient = OkHttpClient.Builder().build()
val request:Request = Request.Builder().url("").build()
//同步请求
client.newCall(request).execute()
//异步请求
client.newCall(request).enqueue(object : Callback{
override fun onFailure(call: Call, e: IOException) {
}
override fun onResponse(call: Call, response: Response) {
}
})
复制代码
二、异步使用源码查看
我们先看一下 client.newCall(request) 方法
/** Prepares the [request] to be executed at some point in the future. */
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
复制代码
可以看出它创建并且返回了一个RealCall对象
再看它的euqueue方法
override fun enqueue(responseCallback: Callback) {
synchronized(this) {
check(!executed) { "Already Executed" }
executed = true
}
callStart()
//diapatcher是线程池调度器
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
复制代码
我们再看一下client.dispatcher.enqueue做了什么
internal fun enqueue(call: AsyncCall) {
synchronized(this) {
readyAsyncCalls.add(call)
// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
// the same host.
if (!call.call.forWebSocket) {
val existingCall = findExistingCallWithHost(call.host)
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
}
}
promoteAndExecute()
}
private fun promoteAndExecute(): Boolean {
this.assertThreadDoesntHoldLock()
val executableCalls = mutableListOf<AsyncCall>()
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
}
//把AsynCall对象添加到executableCalls中,遍历执行其executeOn方法
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
asyncCall.executeOn(executorService)
}
return isRunning
}
复制代码
上面代码的重点是这一句
//把AsynCall对象添加到executableCalls中,遍历执行其executeOn方法
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
asyncCall.executeOn(executorService)
}
复制代码
我们来看一下 asyncCall.executeOn这个方法
fun executeOn(executorService: ExecutorService) {
client.dispatcher.assertThreadDoesntHoldLock()
var success = false
try {
//executorService是一个线程池,它把AsyncCall(一个Runnable对象)添加进去了,
//这样就可以在子线程中执行AsyncCall的run方法了
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!
}
}
}
复制代码
如代码中:Okhttp网络请求异步操作是通过线程池executorService来实现的,它把AsyncCall(一个Runnable对象)添加进去了,这样就可以在子线程中执行AsyncCall的run方法了,我们来看一下AsyncCall的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方法中,执行了getResponseWithInterceptorChain(),并且返回了response,可见这个getResponseWithInterceptorChain()是用来做网络请求的,我们来看一下这个方法
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方法,在这个方法中,会调用到第一个拦截器的intercept方法,这个方法会传入包含了下一个拦截器对象的RealInterceptorChain对象,在intercept方法中,会执行拦截器相关的操作,然后又会调用RealInterceptorChain的proceed方法,依次循环调用,直到调用到CallServerInterceptor,它是最后一个拦截器,最终由它来执行网络请求。整个调用过程使用到了责任链设计模式。
在整个网络请求过程中,Okhttp会使用ConnectionPool连接池来缓存请求连接,以便在下次同一地址,同一端口的网络请求时,可以复用这个连接
在HTTP2.0版本之前,一个链接同时只能做一个请求,在HTTP2.0版本,一个链接可以同时做好几个网络请求,这就是多路复用技术