相信很多人和我一样,对于OKhttp还是停留在只会使用却不知道为什么这么使用的尴尬阶段,敲代码时总有一种照葫芦画瓢,实现了功能不报错就溜之大吉的状态。趁这阶段有空,打算好好捋一捋这个OKhttp,像X光一样把它彻底搞透。(此笔记为个人学习以及复习所用,如果有哪些见解错误,还请包含,恳请指出,蟹蟹~~)
感谢:学习(参考)资料: 泡在网上的日子-OKHttp源码解析 OKHttp3.7源码分析 OKHttp完全解析
整体架构:
1.Interface:接口层,接收网络访问的请求
2.Protocol:协议层,处理协议逻辑
3.Connection:连接层,管理网络连接,发送新的请求,接收服务器访问
4.Cache:缓存层,管理本地缓存
5.InterceptChain:拦截器层,拦截网络访问,插入拦截逻辑
一、Interface——接口层(Call、OKHttpClient、Dispatcher):
接口层接收用户的网络请求(同步、异步),发起实际的网络访问,这里也是我们最常写的代码部分。
OKHttpClient,我们在这里对它进行各种设置,实现各种不同形式的网络请求,每个OKHttpClient内部都维护了属于自己的任务队列,连接池,Cache,拦截器等。所以在使用OkHttp作为网络框架时应该全局共享一个OkHttpClient实例。
这里我们一般自定义一个HttpClientHelper类,在这个类中我们创建OKHttpClient这个实例:
Call:描述的是一个实际的访问请求,我们经常写的这句:mOkHttpClient.newCall(rq).enqueue(newMyCallBack(parser) {});就是我们的实际请求,也就是说每个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.
查看了源代码可以知道,实际执行过程中,OkHttp会为每一个请求创建一个RealCall,每一个RealCall内部有一个AsyncCall
这个AsyncCall它继承了NamedRunnable,并且实现了,execute方法,也就是我们代码最后调用的.execute()
AsyncCall继承的NamedRunnable又继承Runnable,所以每一个Call就是一个线程,而执行Call的过程就是执行其execute方法的过程。
Dispatcher:Dispatcher是OkHttp的任务队列,其内部维护了一个线程池,当有接收到一个Call时,Dispatcher负责在线程池中找到空闲的线程并执行其execute方法。这部分将会单独拿一篇博客进行介绍,详细内容可参考本系列接下来的文章。
二、Protocol——协议层:处理协议逻辑
Protocol层负责处理协议逻辑,OkHttp支持Http1/Http2/WebSocket协议,并在3.7版本中放弃了对Spdy协议,鼓励开发者使用Http/2。
三、Connection——连接层:管理网络连接,发送新的请求,接收服务器访问
在连接层中有一个连接池,统一管理所有的Socket连接,当用户新发起一个网络请求时,OkHttp会首先从连接池中查找是否有符合要求的连接,如果有则直接通过该连接发送网络请求;否则新创建一个网络连接。连接层是OkHttp的核心部分,这部分会在后续单独拿出来做笔记。
四、Cache——缓存层:管理本地缓存
Cache层负责维护请求缓存,当用户的网络请求在本地已有符合要求的缓存时,OkHttp会直接从缓存中返回结果,从而节省网络开销。后面会做详细的笔记。
五、I/O——I/O层:实际数据读写实现
I/O层负责实际的数据读写。OkHttp的另一大有点就是其高效的I/O操作,这归因于其高效的I/O库okio。后面会做详细笔记。
六、Inteceptor——拦截器层:拦截网络访问,插入拦截逻辑
拦截器层提供了一个类AOP接口,方便用户可以切入到各个层面对网络访问进行拦截并执行相关逻辑。后面会做详细笔记。