本文介绍: HttpEngine 在发起请求之前,会先调用nextConnection()来获取一个Connection对象,如果可以从ConnectionPool中获取一个Connection对象,就不会新建,如果无法获取,就会调用createnextConnection()来新建一个Connection对象,这就是 Okhttp 多路复用核心,不像之前的网络框架,无论有没有,都会新建Connection对象。最后,从使用场景看,应用拦截器因为只会调用一次,通常用于统计客户端网络请求发起情况;

Okhttp 基本实现原理
OkHttp 主要是通过 5 个拦截器和 3 个双端队列(2 个异步队列,1 个同步队列工作内部实现通过一个责任模式完成,将网络请求各个阶段封装到各个链条中,实现了各层的解耦。

OkHttp底层是通过 Socket 发送 HTTP 请求与接受响应,但是 OkHttp 实现连接池概念,即对于同一主机多个请求可以公用一个 Socket 连接,而不是每次发送完 HTTP 请求就关闭底层的 Socket,这样就实现连接池概念。而 OkHttp 对 Socket 的读写操作使用的 OkIo 库进行了一层封装
 

执行流程

通过构建者构建出OkHttpClient对象,再通过newCall方法获得RealCall请求对象.

通过RealCall发起同步异步请求,而决定是异步还是同步请求的是由线程分发dispatcher来决定.

当发起同步请求时会将请求加入同步队列中依次执行,所以会阻塞UI线程,需要开启子线程执行.

当发起异步请求时会创建一个线程池,并且判断请求队列是否大于最大请求队列64,请求主机是否大于5,如果大于请求添加异步等待队列中,否则添加到异步执行队列,并执行任务.
 

Okhttp 网络缓存如何实现?

OKHttp 默认支持 get 请求的缓存

Okhttp 网络连接怎么实现复用
HttpEngine 在发起请求之前,会先调用nextConnection()来获取一个Connection对象,如果可以从ConnectionPool中获取一个Connection对象,就不会新建,如果无法获取,就会调用createnextConnection()来新建一个Connection对象,这就是 Okhttp 多路复用核心,不像之前的网络框架,无论有没有,都会新建Connection对象。

Dispatcher功能什么
Dispatcher中文分发器的意思,和拦截器不同的是分发器不做事件处理,只做事件流向。他负责将每一次Requst进行分发,压栈到自己的线程池,并通过调用者自己不同的方式进行异步和同步处理。 通俗的讲就是主要维护任务队列的作用。

记录同步任务、异步任务等待执行的异步任务
调度线程池管理异步任务
发起/取消网络请求 API:execute、enqueuecancel。
Dispatcher 类,该类中维护了三个双端队列(Deque):

readyAsyncCalls准备运行的异步请求
runningAsyncCalls:正在运行的异步请求
runningSyncCalls:正在运行的同步请求
OkHttp 设置默认最大并发请求量 maxRequests = 64 和单个 Host 主机支持最大并发量 maxRequestsPerHost = 5

addInterceptoraddNetworkInterceptor区别
二者通常的叫法为应用拦截器网络拦截器,从整个责任链路来看,应用拦截器是最先执行的拦截器,也就是用户自己设置request属性后的原始请求,而网络拦截器位于ConnectInterceptor和CallServerInterceptor之间,此时网络链路已经准备好,只等待发送请求数据

首先,应用拦截器在RetryAndFollowUpInterceptor和CacheInterceptor之前,所以一旦发生错误重试或者网络重定向,网络拦截器可能执行多次,因为相当于进行了二次请求,但是应用拦截器永远只会触发一次。另外如果在CacheInterceptor中命中了缓存就不需要走网络请求了,因此会存在短路网络拦截器的情况。
其次,如上文提到除了CallServerInterceptor,每个拦截器都应该至少调用一次realChain.proceed方法。实际上在应用拦截器这层可以多次调用proceed方法(本地异常重试)或者不调用proceed方法(中断),但是网络拦截器这层连接已经准备好,可且仅可调用一次proceed方法。
最后,从使用场景看,应用拦截器因为只会调用一次,通常用于统计客户端的网络请求发起情况;而网络拦截器一次调用代表了一定会发起一次网络通信,因此通常可用于计网链路上传输的数据

Okhttp 拦截器的作用是什么?
1、应用拦截器
拿到的是原始请求,可以添加一自定义header、通用参数参数加密网关接入等等。

RetryAndFollowUpInterceptor 处理错误重试重定向

BridgeInterceptor 应用层和网络层的桥接拦截器,主要工作是为请求添加cookie、添加固定的header比如Host、Content-Length、Content-Type、User-Agent等等,然后保存响应结果cookie,如果响应使用gzip压缩过,则还需要进行解压

CacheInterceptor 缓存拦截器,如果命中缓存则不会发起网络请求。

ConnectInterceptor 连接拦截器,内部会维护一个连接池,负责连接复用创建连接(三次握手等等)、释放连接以及创建连接上的socket流。

2、网络拦截器
用户自定义拦截器,通常用于监控网络层的数据传输

CallServerInterceptor 请求拦截器,在前置准备工作完成后,真正发起了网络请求。

Okhttp 有哪些优势?

  1. 支持 http2,对一台机器的所有请求共享同一个 Socket
  2. 内置连接池,支持连接复用,减少延迟
  3. 支持透明gzip 压缩响应
  4. 响应缓存可以完全避免网络重复请求
  5. 请求失败自动重试主机的其他 ip自动重定向
  6. 丰富的 API,可扩展性

response.body().string() 为什么只能调用一次?
我们可能习惯在获取到Response对象后,先response.body().string()打印一遍 Log,再进行数解析,却发现第二次直接抛异常,其实直接跟源码进去看就发现,通过source拿到字节流以后,直接调用closeQuietly()方法关闭了,这样第二次再去通过source读取就直接流已关闭的异常了。

Okhttp 运用了哪些设计模式
Okhttp 运用了六种设计模式

构造模式(OkhttpClient,Request 等各种对象的创建
工厂模式(在 Call 接口中,有一个内部工厂 Factory 接口。)
单例模式(Platform 类,已经使用 Okhttp 时使用单例
策略模式(在 CacheInterceptor 中,在响应数据选择使用策略模式,选择缓存数据还是选择网络访问。)
责任链模式(拦截器的链式调用)
享元模式(Dispatcher 的线程池中,不限量的线程池实现了对象复用
 

原文地址:https://blog.csdn.net/2301_76766616/article/details/134660494

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_23924.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注