还有一个框架Retrofit,这个框架也比较火,但是需要明确:这个框架是对OkHttp的封装,框架本身并不具备网络请求的能力,框架增加了线程切换、解析器适配器等让OkHttp更加容易使用。
http1.1 增加了keep-alive 的功能,这个可以通过客户端控制,也可以通过服务端控制。
Connection keep-alive 表示开启保持连接的功能,close 表示关闭。
Http1.1的版本,发起的请求必须是串行的。
Http2一下的版本,OkHttp增加了一个对象池,复用连接。
val okHttpClient = OkHttpClient.Builder()
// .cache(Cache(File("/"),1024)) //设置缓存
// .addInterceptor() //添加拦截器
//.callTimeout() 设置请求超时
//.connectTimeout() 设置连接超时
//.dispatcher()//设置分发器
// .dns() 设置自己的dns
.eventListener(OkHttpListener()) //设置事件监听器
.build()
val request = Request.Builder()
.url("https://www.baidu.com/") //设置网络连接
// .addHeader("","")//添加请求头
// .cacheControl(CacheControl.FORCE_NETWORK) //添加擦车策略
// .post(RequestBody) //默认是Get请求,如果需要使用post请求,需要设置一个RequestBody
.build()
val newCall = okHttpClient.newCall(request) //得到Call 对象
// val result=newCall.execute()//表示同步执行 ,同步可以直接得到一个结果
// println(result.isSuccessful) isSuccessful通过这个来判断是否请求成功
// result.body// 拿到请求体,可以通过流的方式进行读取
// result.close()
newCall.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
//请求失败的回调
Log.e("lpf", "onFailure-------->请求失败")
}
override fun onResponse(call: Call, response: Response) {
//请求成功的回调
if (response.isSuccessful) {
Log.d("lpf", "isSuccessful")
response.body?.let { Log.d("lpf", it.string()) }
} else {
Log.e("lpf", "请求失败")
}
}
}) //这个表示异步请求 异步请求需要传入一个回调
//事件回调
class OkHttpListener:EventListener(){
override fun callStart(call: Call) {
super.callStart(call)
Log.e("lpf","callStart-------->")
}
override fun callEnd(call: Call) {
super.callEnd(call)
Log.e("lpf","callEnd-------->")
}
override fun connectStart(
call: Call,
inetSocketAddress: InetSocketAddress,
proxy: Proxy
) {
super.connectStart(call, inetSocketAddress, proxy)
Log.e("lpf","connectStart-------->")
}
override fun connectEnd(
call: Call,
inetSocketAddress: InetSocketAddress,
proxy: Proxy,
protocol: Protocol?
) {
super.connectEnd(call, inetSocketAddress, proxy, protocol)
Log.e("lpf","connectEnd-------->")
}
override fun dnsStart(call: Call, domainName: String) {
super.dnsStart(call, domainName)
Log.e("lpf","dnsStart-------->")
}
override fun dnsEnd(
call: Call,
domainName: String,
inetAddressList: List<InetAddress>
) {
super.dnsEnd(call, domainName, inetAddressList)
Log.e("lpf","dnsEnd-------->")
}
override fun requestBodyStart(call: Call) {
super.requestBodyStart(call)
Log.e("lpf","requestBodyStart-------->")
}
override fun requestBodyEnd(call: Call, byteCount: Long) {
super.requestBodyEnd(call, byteCount)
Log.e("lpf","requestBodyEnd-------->")
}
override fun responseHeadersStart(call: Call) {
super.responseHeadersStart(call)
Log.e("lpf","responseHeadersStart-------->")
}
override fun requestHeadersEnd(call: Call, request: Request) {
super.requestHeadersEnd(call, request)
Log.e("lpf","requestHeadersEnd-------->")
}
}
打印的事件回调结果
2022-05-17 22:53:29.127 8954-8954/com.test.kotlin_test E/lpf: callStart-------->
2022-05-17 22:53:29.132 8954-9191/com.test.kotlin_test E/lpf: dnsStart-------->
2022-05-17 22:53:29.193 8954-9191/com.test.kotlin_test E/lpf: dnsEnd-------->
2022-05-17 22:53:29.197 8954-9191/com.test.kotlin_test E/lpf: connectStart-------->
2022-05-17 22:53:29.289 8954-9191/com.test.kotlin_test E/lpf: connectEnd-------->
2022-05-17 22:53:29.292 8954-9191/com.test.kotlin_test E/lpf: requestHeadersEnd-------->
2022-05-17 22:53:29.319 8954-9191/com.test.kotlin_test E/lpf: responseHeadersStart-------->
2022-05-17 22:53:29.323 8954-9191/com.test.kotlin_test D/lpf: isSuccessful
2022-05-17 22:53:29.327 8954-9191/com.test.kotlin_test E/lpf: callEnd-------->
/** Prepares the [request] to be executed at some point in the future. */
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
override fun enqueue(responseCallback: Callback) {
check(executed.compareAndSet(false, true)) { "Already Executed" }
callStart()
//事件分发器dispatcher 要分发任务了(敲黑板,重点在这里)
client.dispatcher.enqueue(AsyncCall(responseCallback))
}
//事件分发
internal fun enqueue(call: AsyncCall) {
synchronized(this) {
//将RealCall加入到队列
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) { //如果不是websocket
//查找之前请求的call的host跟我们这次请求的是否是一样的
val existingCall = findExistingCallWithHost(call.host)
//如果存在就拿到之前的call的host
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
}
}
promoteAndExecute()
}
这个方法就是将newCall添加到了等待队列,然后将Host的数量做了运算。
/**
* 将符合条件的调用从 [readyAsyncCalls] 提升到 [runningAsyncCalls] 并在 executor 服务上运行它们。
* 不能同步调用,因为执行调用可以调用用户代码。
* 如果调度程序当前正在运行调用,则为 true
*/
private fun promoteAndExecute(): Boolean {
this.assertThreadDoesntHoldLock()
//定义一个临时缓存
val executableCalls = mutableListOf<AsyncCall>()
val isRunning: Boolean
synchronized(this) {
val i = readyAsyncCalls.iterator()
//遍历等待连接池中的RealCall
while (i.hasNext()) {
val asyncCall = i.next()
//限制 最多同时执行的任务数量
if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
//同一个Host同时执行的任务数量最多是5个 如果超过5个了,continue
if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.
i.remove()
asyncCall.callsPerHost.incrementAndGet()
executableCalls.add(asyncCall) //将newCall添加到缓存数组里边
runningAsyncCalls.add(asyncCall) //添加到正在运行的队列
}
isRunning = runningCallsCount() > 0
}
//遍历缓存数组
for (i in 0 until executableCalls.size) {
val asyncCall = executableCalls[i]
asyncCall.executeOn(executorService)
}
return isRunning
}
fun executeOn(executorService: ExecutorService) {
client.dispatcher.assertThreadDoesntHoldLock()
var success = false
try {
//将call放置到线程池 就执行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) { //当这个call执行完成了,最终会执行这里
client.dispatcher.finished(this) // This call is no longer running!
}
}
}
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
try {
//通过执行getResponseWithInterceptorChain 获取到请求的结果(重点--拦截器来了)
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)
}
}
}
}
@Throws(IOException::class)
internal fun getResponseWithInterceptorChain(): Response {
// Build a full stack of interceptors.
val interceptors = mutableListOf<Interceptor>()
//添加我们自定义的 Interceptor 添加到请求器数组里边
interceptors += client.interceptors
//添加重试和跟进拦截器
interceptors += RetryAndFollowUpInterceptor(client)
//桥梁拦截器 :应用程序代码到网络代码的桥梁
interceptors += BridgeInterceptor(client.cookieJar)
//缓存拦截器 处理来自缓存的请求并将响应写入缓存
interceptors += CacheInterceptor(client.cache)
//连接拦截器 打开到目标服务器的连接并继续到下一个拦截器。网络可能用于返回的响应,或使用条件 GET 验证缓存的响应。
interceptors += ConnectInterceptor
if (!forWebSocket) {
//添加我们自定义的NetworkInterceptor
interceptors += client.networkInterceptors
}
//这是链中的最后一个拦截器。它对服务器进行网络调用
interceptors += CallServerInterceptor(forWebSocket)
//将拦截器构建成 拦截器链RealInterceptorChain
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 {
//通过责任链的方式,proceed request 得到response
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)
}
}
}
OkHttp默认有5个拦截器,通过拦截器真正的执行网络请求,并返回数据。这块采用的是责任链的设计模式来设计的。
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)
}
}
采用责任链的设计模式,是一种行为性设计模式,让我们的任务请求者和发起者进行解耦合,我们不需要关心责任链是如何处理的。