OkHttp 3,下血本买的

OkHttp 3,下血本买的,第1张

OkHttp 3,下血本买的

对于OkHttp整体框架的介绍,网上的文章有很多,同时也配有一些图解(当然很多都是一样的就是了),总体上我和大家的理解也是相近的。但是呢,我觉得还不够具体也不够完善,因为我想知道,如果我自己要实现一个HttpClient到底要做到什么程度?所以我希望能更加详细地去理解OKHttp的设计和实现。

下面这幅是我自己描绘的OkHttp框架层次图(图比较大可能需要鼠标左键图片才能看清楚):

下面先来简单介绍一下OkHttp的各个层次,后面会有更加详细的文章专门去解读它们。

OkHttpClient

OkHttpClient在一个应用往往只会创建一个单例。

对外主要是两个功能:一个是可配置,比如你可以设置超时时间,配置自定义的cookieJar实现,配置多个自定义的Interceptor实现,添加事件监听等等;另外一个是提供newCall API,我们用的最多也是这个API。

对内它的配置会被全局范围内使用,同时也负责创建和管理一些全局单例对象,比如Dispatcher、ConnectionPool等。

所以OkHttpClient有点类似一个全局的应用上下文。

Dispatcher

Dispatcher主要管理异步请求任务策略,负责分配异步线程资源,控制异步连接数,只覆盖线程资源层面的逻辑,往下的执行过程对其来说是透明的。

而对于同步任务,Dispatcher只是简单记录当前运行的任务实体(RealCall),并且是由RealCall主动注册和注销。

Dispatcher是final类,不提供扩展接口,但是Dispatcher
存在两个构造方法:Dispatcher()和Dispatcher(ExecutorService)。OkHttpClient默认会使用无参构造函数创建一个全局的单例对象,该对象使用内置的线程池来执行异步任务,如果用户想使用自定义线程池,那么可以通过使用有参构造函数创建一个新的Dispatcher对象,并且通过OkHttpClient.Builder设置进去。

Call

OkHttp一次用户请求任务的接口定义,有两个实现:RealCall和AsyncCall,前者是同步任务,后者是异步任务。

这里我之所以把Call称作为“一次用户请求”,是因为一次OkHttp请求和响应,中间可能夹着多个请求和响应,比如代理服务的认证、失败重试、重定向等等,但是这些对于OkHttp的使用者来说都是透明的,他们很多时候只需要感知最初的请求和最后的结果即可,而Call是包含中间这些所有的过程的,因此我把Call称为“一次用户请求”。

Interceptor调用

Interceptor接口在OKHttp包下有5个内置实现,也就是上图中最大的那一个框。它们通过责任链的方式调用,实现了Http协议的整个流程,当然这个流程指的是应用层协议的流程,不包括底下传输层的实现。

Interceptor是可扩展可配置的,用户可以自定义实现Interceptor接口,并且通过OkHttpClient添加到Http流程的实现中去。

OKHttpClient有两个可配置的Interceptor集合(它们默认都是空的):interceptors和networkInterceptors。interceptors会被添加到调用链的最前面;而networkInterceptors则会被添加到Socket连接之后,Socket读写数据之前。但是如果是WebSocket请求,networkInterceptors集合则不会被添加到调用链中去。

Response getResponseWithInterceptorChain() throws IOException {

// Build a full stack of interceptors.

List interceptors = new ArrayList<>();

//用户自定义的拦截器会在请求最开始被调用,也就是递归的最上层

interceptors.addAll(client.interceptors());

//失败重试,代理认证、重定向等

interceptors.add(new RetryAndFollowUpInterceptor(client));

//重写请求和响应头,cookie存储

interceptors.add(new BridgeInterceptor(client.cookieJar()));

//Http缓存流程实现

interceptors.add(new CacheInterceptor(client.internalCache()));

//发起Socket连接

interceptors.add(new ConnectInterceptor(client));

//Socket连接和数据读写之间,但是WebSocket请求不会添加这个拦截器集合

//可能WebSocket,数据通信走的是传输层,而Interceptor是应用层协议的接口?

if (!forWebSocket) {

interceptors.addAll(client.networkInterceptors());

}

//数据的读写,真正的网络I/O

interceptors.add(new CallServerInterceptor(forWebSocket));

}

Transmitter

Transmitter翻译过来有“传输者、传播者”的意思,所以在这里我还是用上下文来称呼它,作用域是整个Call任务。

Transmitter会在Interceptor调用链中相互传递,Interceptor会通过Transmitter对象的属性或者方法对底下的传输层进行 *** 作,Transmitter对调用者屏蔽了传输层的实现细节,让Interceptor调用链专注于应用层协议的实现。

Transmitter管理着Call任务的很多状态(比如请求开始、请求结束、失败、取消等等),调用者随时可以获取Call的状态从而实现相应的逻辑处理,也可以根据处理的结果更新其状态。

Transmitter还持有用户配置,实现了超时回调机制等等。

Transmitter往下的代码耦合性挺强的,层次之间其实没有上面那图那么清晰,它直接会存在一些交叉,彼此之间相互调用,个人觉得这部分代码可读性是挺差的 - -!。同时多数类都是final类,并不向上提供接口,也就是这部分代码是不可扩展的,只是留有一些可配置的参数属性(比如:连接池最大空闲连接数),我不知道这是OkHttp历史版本迭代的原因,还是作者有意这样设计,如果有小伙伴对这方面有了解的话,希望可以留言跟大家分享一下。

inal类,并不向上提供接口,也就是这部分代码是不可扩展的,只是留有一些可配置的参数属性(比如:连接池最大空闲连接数),我不知道这是OkHttp历史版本迭代的原因,还是作者有意这样设计,如果有小伙伴对这方面有了解的话,希望可以留言跟大家分享一下。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5708521.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存