探索OkHttp网络请求核心代码
一、OkHttp是什么
OkHttp与Retrofit一样,同出一处,二者皆是极为优秀的开源框架,HTTP是现代应用程序网络的方式。这就是我们交换数据和媒体的方式。有效地执行HTTP可以使您的内容加载更快并节省带宽。
OkHttp是默认情况下有效的HTTP客户端:
- HTTP / 2支持允许对同一主机的所有请求共享一个套接字。
- 连接池可减少请求延迟(如果HTTP / 2不可用)。
- 透明的GZIP缩小了下载大小。
- 响应缓存可以完全避免网络重复请求。
当网络出现问题时,OkHttp会坚持不懈:它将从常见的连接问题中静默恢复。如果您的服务具有多个IP地址,则在第一次连接失败时,OkHttp将尝试使用备用地址。这对于IPv4 + IPv6和冗余数据中心中托管的服务是必需的。OkHttp支持现代TLS功能(TLS 1.3,ALPN,证书固定)。可以将其配置为回退以获得广泛的连接性。
使用OkHttp上手容易简单。它的请求/响应API具有流畅的构建器和不变性。它支持同步阻塞调用和带有回调的异步调用。
二、Retrofit与OkHttp的关系
简单来说Retrofit是针对Java或Android基于OkHttp之上进一步的封装,Retrofit依赖于OkHttp,将网络请求的核心部分交给OkHttp执行,Retrofit使用注解方式,大大简化了我们的URL 拼写形式,而且注解含义一目了然,简单易懂; 支持多种文件格式解析(JSON,GSON,XML等); 实现强大的同步与异步执行,使得请求变得更易入手。
三、OkHttp核心源码解析
在学习这些核心代码过程中,完全是以个人的角度及结合了一些官方文档、网络资料进行的,所以,有哪些地方解析有误,也望大家在评论中指出一二。
言归正传,抛开OkHttp核心以外的方法,我们慢慢深入OkHttp网络请求核心的部分,其核心部分可以分三个点切入分析:
- (Where)请求发送到哪里了
- (Who)请求被谁处理了
- (How) 请求是怎么维护的
首先,来一个简单的网络请求的简单例子:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//构建OkHttpClient
val client = OkHttpClient.Builder().build()
//构建Request
val request = Request.Builder().url(Api.BASE_URL).build()
//创建Call接口对象
val call = client.newCall(request)
//异步请求
call.enqueue(object : Callback {
//异步请求失败
override fun onFailure(call: Call, e: IOException) {
Log.e("FAIL", "请求失败---->${
e.message}")
}
//异步请求成功
override fun onResponse(call: Call, response: Response) {
Log.e("Success", "请求数据---->${
response.body}")
}
})
}
}
根据代码发现,通过call
接口对象调用enqueue()
入队的回调Callback
实现的两个方法(onFailure和onResponse)
中获取响应数据结果,所以核心的切入点是从call.enqueue(Callback回调)
开始的。
1、(Where)请求发送到哪里了
在上面的简单的例子中,我们发现请求是被送入队列中的,通过call.enqueue(Callback回调)
入队,进入enqueue方法我们发现:
interface Call : Cloneable {
...
fun enqueue(responseCallback: Callback)
...
}
enqueue其实是Call
接口定义需要实现的入队方法,那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 {
...
//请求进入队列
override fun enqueue(responseCallback: Callback) {
check(executed.