OKhttp源码解析

216 阅读3分钟
  1. OKhttp官方API地址 (square.github.io/okhttp/)

2.概述 高效地使用HTTP可以使你的文件加载更快,节省带宽,也就是说OKhttp是一个执行效率比较高的HTTP客户端

  • 支持HTTP/2 ,当多个请求对应同一host地址时,可共用同一个socket;(http2多路复用)

  • 连接池可减少请求延迟(如果HTTP/2不可用);

  • 支持GZIP压缩,减少网络传输的数据大小;

  • 支持Response数据缓存,避免重复网络请求;

3.OKhttp使用方法简介

20220522160748.jpg

20220522160834.jpg

4.源码解析

OKhttp分为同步请求,异步请求

4.1同步请求 同步请求请求的逻辑相对简单,我们从execute()方法查看

20220522161134.jpg 可以看到这Call是一个接口,定义了一个方法execute(),我们去找真正实现这个方法的地方,在前面我们通过cilent.newCall()方法执行的execute()方法,我们去看看newCall是个什么?做了那些事?

20220522161508.jpg 可以看到newCall()方法就是创建了一个RealCall对象,然后将前面我们通过构建者模式创建的OKHttpCilent和Request传了进去,有个点我们看到还有个参数 forWebSocket,这个参数是个啥?

forwebSocket这个其实不重要,它也是一个应用层的交互协议,像Http一样,我们都知道最初HTTP交互是客户端和服务端进行一来一回的交互,服务端是不能和客户端主动交互的(新版HTTP除外),WebSocket是服务器可以主动给客户端发消息的。我们平时开发很少用到,像那种需要频繁和服务器交互的比如股票软件,这种需要快速及时的刷新数据的。感兴趣的可以看看   

20220522163221.jpg 接着回归正题,我们看下RealCall的excute()方法

20220522163014.jpg 可以看到这块主要是调用了cilent的dispatcher()方法

20220522163221.jpg将call对象加入到了runningSynCalls里面,再看看这个runningSynCalls

20220522163357.jpg很简单就是一个双端队列,加进去之后呢,肯定是要进行请求分发,我们回到RealCall的execute()方法,之后的方法 getResponseWithInterceptorChain()。具体对HTTP封装,结果的处理就是在这个方法里面了。我们后面再看,因为我们还要看看异步方法怎么发起请求的?

4.2异步请求

和上面一样,我们直接定位到RealCall的enqueue方法

20220522163930.jpg 这一块传入了一个AsyncCall对象

20220522164243.jpg AsyncCall也就是一个Runable,那最终还是要调用run()方法的,不要慌,先插眼,我们后面看

接着和同步方法一样,我们看DisPatcher的enqueue方法

20220522164545.jpg 可以看到,将AsynCall加入到了 readyAsyncCalls 里面,然后调用 promoteAndExecute()方法 ,所以我们看这个方法

20220522164910.jpg readyAsyncCalls 和runningAsyncCalls都是一个双端队列,这块加锁限制了最大请求并发数,和同个主机最大连接数

20220522165433.jpg

20220522165419.jpg 对外暴露set()方法,说明可以配置,最终遍历执行asynCall.executeOn()方法,回到我们上面插眼的地方

20220522165702.jpg 通过线程池创建启动线程,也就到了我们刚说的AsyncCall的run方法()

总结下请求前置部分:

  • 使用了构建者设计模式,封装了构建过程和细节
  • 请求分为同步请求和异步请求。
  • 同步请求将请求加入到了一个双端队列里面,然后开始发起请求
  • 异步请求每次都会创建一个线程也就是AsynCall,然后请求先加入到准备请求队列,然后判断最大并发数,同一主机最大连接数,如果满足则开始遍历执行线程的run方法,发起请求 未完待续