很久之前看过
OkHttp
的源码,但当时没有做总结,今天突然想在脑海中过一遍OkHttp
内部的执行流程时,发现一片混沌不知从何说起,于是今天重新过了一遍,参考了一篇从源码角度进行解析的文章并做了总结,需要详细源码解读的可以去看看这篇文章,这里只做总结,不重复造轮子,网上详细解析OkHttp
的优秀文章也很多。
先看一张流程图(来自这篇文章),另外推荐博主的另一篇Retrofit解读:
整体流程:
整个流程是,通过
OkHttpClient
的newCall()
将构建的Request
转换为Call
,Call
内部调用RealCall
,然后在RealCall
中进行异步或同步任务,最后通过一系列的拦截器interceptor
发出网络请求和得到返回的response
1 具体执行流程:
整个请求流程是从RealCall开始的:
1.1 如果是同步请求( execute()
):
则会调用
dispatcher
的executed()
方法将请求任务加到同步请求运行队列中(即runningSyncCalls.add(call);
)然后调用getResponseWithInterceptorChain()
,该方法中通过执行一系列的拦截器完成整个网络的请求任务,最后会调用dispatcher
的finished()
方法告知我们执行完毕了
1.2 如果是异步请求(enqueue()
):
主要用到了调度器
Dispatcher
,我们调用enqueue()
方法后,在
RealCall
中会去调Dispatcher
的enqueue()
方法,这个方法会判断当前的请求数量从而决定要将该请求添加到等待队列还是添加到异步执行队列中利用线程池去执行。执行的时候调用的还是
getResponseWithInterceptorChain()
从而还是通过一系列的拦截器来完成网络请求,不同的是这里是利用线程池来异步执行任务。
2 这个Dispatcher拦截器是什么?:
Dispatcher
在同步请求中的作用只是用于告知我们执行状态,例如开始执行了(调用executed()
)以及运行结束了(调用finished()
)
其主要作用是在异步执行过程中,
Dispatcher
的enqueue()
方法会判断当前的请求数量从而决定要将该请求添加到等待队列还是添加到异步执行队列中利用线程池去执行。任务的异步执行真是在这里完成分配的。
3 拦截器又是什么?
3.1 首先
RealCall中真正发起网络请求以及解析返回结果的,是getResponseWithInterceptorChain() ,这个方法中将一系列的拦截器例如 重定向拦截器、转换拦截器、缓存拦截器、连接拦截器等 添加到一个
ArrayList
后通过一系列的链式调用执行各个拦截器;
3.2 具体的拦截器包括:
- 负责失败重试以及重定向的 RetryAndFollowUpInterceptor;
- 负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的 BridgeInterceptor
- 负责读取缓存直接返回、更新缓存的 CacheInterceptor(判断是要去获取网络的Response还是直接使用缓存);
- 负责和服务器建立连接的 ConnectInterceptor;
- 配置
OkHttpClient
时设置的 networkInterceptors;- 负责向服务器发送请求数据、从服务器读取响应数据的 CallServerInterceptor。
3.3 总的来说
拦截器是将请求一层一层向下传,直到有一层能够得到
Response
就停止并将Response
向上面的拦截器传递,然后各个拦截器会对Response
进行一些处理最后传到RealCall
类中返回
Interceptor的设计体现了设计模式中的单一职责原则
Interceptor 的设计是一种分层的思想,每个 Interceptor 就是一层。分层简化了每一层的逻辑,每层只需要关注自己的责任,而各层之间通过约定的接口/协议进行合作(面向接口编程思想),共同完成复杂的任务。