OkHttp3分析

OkHttp3是一个精巧的网络请求库,有如下特性

  • 1)支持HTTP2,对一台机器的所有请求共享同一个socket
  • 2)内置连接池,支持连接复用,减少延迟
  • 3)支持透明的gzip压缩响应体
  • 4)通过缓存避免重复的请求
  • 5)请求失败时自动重试主机其他的ip,自动重定向
  • 6)好用的API

OkHttp请求划分为三个阶段

  • 1 OKHttpClient+Request构造RealCall
  • 2 RealCall直接同步执行或者进入异步队列,同一有Dispatcher分发
  • 3 通过Interceptor的责任链,层层调用,最后获取Response

实现网络请求方法

OkHttp3的最底层是Socket,而不是URLConnection,它通过Platfrom的Class.forName()反射获得当前Runtime使用的socket库

Socket发起网络请求的一般流程是:

  • (1) 创建socket对象
  • (2) 连接到目标网络
  • (3) 进行输入输出流操作

(1)(2)的实现,封装在connection接口中,具体的实现类是RealConnection。

(3) 通过stream接口来实现,根据不同的网络协议,有Http1XStream和Http2xStream两个实现类,由于创建网络连接的时间较久(如果是HTTP的话,需要进行三次握手),而请求经常是频繁的碎片化的,所以为了提高网络连接的效率,OkHttp3实现了网络连接的复用。

运用到的设计模式

  • 1 单例模式:
  • 2 外观模式:OkHttpClient里面组合了很多类对象。其实是将OKHttp的很多功能模块,全部包装进这个类中,让这个类单独提供对外的API,这种设计叫做外观模式(外观模式:隐藏系统的复杂性,并向客户端提供一个客户端可以访问系统的接口)
  • 3 Builder模式:OkHttpClient比较复杂,太多属性,而且客户的组合需求多样化,所以OkHttp使用建造者模式(Build模式:使用多个简单的对象一步一步构建成一个复杂的对象,一个Builder会一步一步构造最终的对象)
  • 4 工厂方法模式:Call接口提供了内部接口Factory(用于将对象的创建延迟到该工厂类的子类中进行),从而实现动态的配置。(工厂方法模式:这种类型属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,并且使通过使用一个共同的接口来指向新创建的对象。)
  • 5 享元模式:在Dispatcher的线程池中,用到了享元模式,一个不限容量的线程池,线程空闲时存活时间为60秒。线程池实现了对象复用,降低线程创建开销,从设计模式上来讲,使用了享元模式(享元模式:尝试重用现有的同类对象,如果未找到匹配对象,则创建新对象,主要用于减少创建对象的数量,以减少内存占用和提高性能)
  • 6责任链模式:很明显,在Okhttp中拦截器模块,执行过程用到。OkHttp3的拦截器链中,内置了5个默认的拦截器,分别用于重试、请求对象转换、缓存、链接、网络读写(责任链模式:为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接受者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接受者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接受者,依此类推)
  • 7策略模式:CacheInterceptor实现了数据的选择策略,来自网络还是来自本地?这个场景也是比较契合策略模式场景,CacheInterceptor需要一个策略提供者提供它的一个策略,CacheInterceptor根据这个策略去选择走网络场景还是本地缓存。

缓存策略的过程:

  • 1、请求头包含(IF-Modified-Since)或"If-None-Match"暂时不走缓存
  • 2、客户端通过cacheControl指定了无缓存,不走缓存
  • 3、客户端通过cacheControl指定了缓存,则看缓存过期时间,符合要求走缓存
  • 4、如果走了网络请求,响应状态码为304(只有客户端请求头包含"If-Modified-Since"或"If-None-Match",服务器数据没变化的话会返回304状态码,不会返回响应内容),便是客户端继续用缓存。
  • (策略模式:一个类的行为或其算法可以在运行时更改,这种类型的设计模式属于行为型模式。策略模式中,我们闯将表示各种策略和一个行为随着对象改变而改变的context对象。策略对象改变context对象的执行算法。)

源码中用到的几个重要的类及作用解释

1 OkhttpClient

对外的API,OKHttp的很多功能模块,全部包装进这个类;创建分为两种:
一种是new OKHttpClient()的方式,另一种是使用建造者(Builder)模式–new OKHttpClient.Build()…Build()

  • 第一种:new OkHttpClient(),OkHttp做了很多工作,很多我们需要的参数在这里获得默认值,者就是默认设定。
  • 第二种:默认的设置和第一种相同,但是我们可以利用建造者模式单独的设置每一个属性;注意事项:OKHttpClient强烈建议全局单例使用,因为每一个OkHttpClient都有自己单独的连接池和线程池,复用连接池和线程池能减少延迟、节省内存

2、RealCall类:集成Call类,从源代码中,可以看到使用Call类,发送出(同步/异步)请求,RealCall的主要作用:发送请求,当中还有拦截器和建立过程,异步回调。

#### 3、Dispatcher类(调度器、多线程):保存同步和异步Call的地方,并负责执行异步AsyncCall

4、拦截器链:有供用户自定义的Interceptor、RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectIntercepyor、NetworkInterceptors、CallServerInterceptor,依次通过以上拦截器,传递给RealCall中的ApplicationInterceptorChain。拦截器之所以可以依次调用,并最终再在从后往前返回Response,都依赖于ApplicationCationInterceptorChain的proceed方法、BridgeInterceptor的主要作用就是为请求(request before)添加请求头,一个拦截器的intercept方法所执行的逻辑分为三部分:

  • 在发起请求前对request进行处理
  • 调用下一个拦截器,获取response
  • 对response进行处理,返回给上一个拦截器

5 HttpEngine类:

核心拦截器

缓存策略:提到缓存策略,就要提到CacheInterceptor拦截器

image

CacheStrategy实现缓存策略,CacheStrategy使用Fatory模式进行构造,该类决定是使用缓存还是使用网络请求
Cache封装了实际的缓存操作
DiskLruCache:Cache基于DiskLruCache

RetryAndFollowUpInterceptor

RetryAndFollowUpInterceptor逻辑分为两部分
  • 1 在网络请求失败后进行重试,
  • 2 当服务器返回当前请求需要进行重定向时直接发起新的请求,并在条件允许的情况下复用当前连接
BridgeInterceptor主要负责添加请求头
  • 1 设置内容长度,内容编码
  • 2 设置gzip压缩,并在接收到内容后进行解压,省去了应用层数据解压的麻烦
  • 3 添加cookie
  • 4 设置其他报头,如User-Agent、Host,Heep-Alive
CacheInterceptor的职责很明确,就是负责Cache的管理
  • 1 当网络请求符合要求的Cache时直接返回Cache
  • 2 当服务器返回内容有改变时更新当前cache
  • 3 如果当前Cache失效,删除
  • 4 在CacheInterceptor内部使用了策略模式
ConnectInterceptor的intercept只有一行关键代码
  • 1 即为当前的请求找到合适的连接,可能复用已经有链接也可能重新创建连接,返回的连接由连接池决定

CallServerInterceptor

  • 1 负责向服务器发起真正的访问请求,并在接收到服务器后读取响应返回
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章