OKhtt原理以及异步执行过程
先上图,这是Okhttp官网文档的一张OKhttp请求执行流程和经过的拦截器,并且服务器响应的时候经过的拦截器。
大家看这张图的时候按照流程执行,这是okhttp的请求执行过程,从应用发出request,到应用收到response,期间经历了N个拦截器,可以看出Okhttp的拦截器在整个请求的过程中起到了重大作用,扮演者中要的角色。
拦截器的作用:
官方文档翻译
Rewriting Requests
Interceptors can add, remove, or replace request headers. They can also transform the body of those requests that have one. For example, you can use an application interceptor to add request body compression if you're connecting to a webserver known to support it.
拦截器可以对每一个请求头中的信息进行,添加,移除,或者替换。如有请求中有请求体的话还可以对请求体里里面的内容做转换。比如,你可以给你的应用增加一个”内容压缩的拦截器“,对请求体中的内容进行压缩,前提是你请求的服务器能支持你这种压缩后的请求内容,所以要实现类型功能请后端必须沟通好,比如前端采用什么样的压缩算法,后端接收到请求后,采用相同的算法解压。不过一般来说我们都不会采用这种拦截器,因为okhttp 默认就支持GZIP压缩
OKhttp3 核心
Okhttp3 是一个高性能网络请求框架,支持支持HTTPS/HTTP2/WebSocket ,其核心有一下几点:
1、采用责任链方式的拦截器,实现分成处理网络请求,让用户对网络请求实现了更好的扩展
2、GZIP处理降低了下载数据的大小
3、支持http 缓存
4、采用线程池(thread pool)和连接池(socket pool)解决多并发问题,同时连接池采支持多路复用(http2才支持多路复用,单路复用指的是,个socket 只有把一个请求发送完成后,才能继续发送第二个请求,多路复用可以让一个socket 同时发送多个请求的数据,内部会自动维护顺序),减少连接创建开销
5、底层采用 socket 和服务器进行连接。
6、采用okio 实现高效的io流读写
OkhttpCore(内置5大核心拦截器)
上图拦截器流程示意图中,其中OkhttCore 包含了五大核心拦截器,它们承担了整个网络请求的全部工作。
1.RetryAndFollowUpInterceptor
RetryAndFollowUpInterceptor 的作用,看到该拦截器的名称就知道,它就是一个负责失败重连和重定向的拦截器。它是 Okhttp 内置的第一个拦截器,通过 while (true) 的死循环来进行对异常结果或者响应结果判断是否要进行重新请求。
2.BridgeInterceptor
BridgeInterceptor 为用户构建的一个 Request 请求转化为能够进行网络访问的请求,同时将网络请求回来的响应 Response 转化为用户可用的 Response。比如,涉及的网络文件的类型和网页的编码,返回的数据的解压处理等等。
3.CacheInterceptor
CacheInterceptor 根据 OkHttpClient 对象的配置以及缓存策略对请求值进行缓存。
4.ConnectInterceptor
ConnectInterceptor 在 OKHTTP 底层是通过 SOCKET 的方式于服务端进行连接的,并且在连接建立之后会通过 OKIO 获取通向 server 端的输入流 Source 和输出流 Sink。
5.CallServerInterceptor
CallServerInterceptor 在 ConnectInterceptor 拦截器的功能就是负责与服务器建立 Socket 连接,并且创建了一个 HttpStream 它包括通向服务器的输入流和输出流。而接下来的 CallServerInterceptor 拦截器的功能使用 HttpStream 与服务器进行数据的读写操作的。
自定义拦截器
1.应用拦截器 Application Interceptor
2.网络拦截器 NetWork Interceptor
他们的异同:
相同点
1)都能对server返回的response进行拦截
2)这两种拦截器本质上都是基于Interceptor接口,由开发者实现这个接口,然后将自定义的Interceptor类的对象设置到okhttpClient对象中,所以,本质上没什么不同,都是Interceptor的实现类的对象。
3)两者都会被add到OkHttpClient内的一个ArrayList中。当请求执行的时候,多个拦截器会依次执行(list本身就是有序的)。
不同点
1)okhttpClient添加两种拦截器的api不同。添加应用拦截器的接口是addInterceptor(),而添加网络拦截器的接口是addNetworkInterceptor().
2)两者负责的区域不同,从最上方图中可以看出,应用拦截器作用于okhttpCore到Application之间,网络拦截器作用于 network和okhttpCore之间
3)在某种特殊情况下(比如:访问了一个url,结果这个url发生了重定向),网络拦截器有可能被执行多次,但是 不论任何情况,application只会被执行一次。
核心源码
构建完成Request的后通关newCall发送请求返回一个Call对象后执行异步请求
进到RealCall类中的异步方法 看到最后一行代码,okhttpclient对象调用dispatcher方法返回一个dispatcher对象进行调用dispatcher中的异步方法将call放入异步任务中并将匿名异步任务对象传入道此方法中, 这里的使用的链式编程
进入到disparcher中找到enqueue方法
这里首先是将异步任务添加到了一个准备任务队列中,
if判断中是对正在执行的任务队列或者准备执行的任务队列中找之前执行的异步任务 AsyncCall,首先去准备任务队列中去寻找,找不到了再去正在执行的任务队列中去找,
找到之后去判断是否为空,不为空的话会将找的异步任务传入ReakCall中赋值给本次异步任务(AtomicInteger 一个计数器,线程安全),这个后面会提到。
最后调用的promoteAndExecute() 这个方法大家从字面意思上看大概也知道这就是准备执行了,
Dispatcher 的promoteAndExecute 方法: