Android OkHttp拦截器源码分析一--简介
拦截器OkHttp强大功能
拦截器使用了责任链设计模式,Okhttp源码中拦截器共有五个
在拦截器中我们可以做自定义缓存,设置网络请求重试次数,以及打印网络请求日志
等等...很多其他网络请求框架实现不了的需求
1. RetryAndFollowUpInterceptor
- 处理重试的拦截器,也会去处理一些异常
- 只要不是致命的异常就会重新发起一次请求,如果是致命的异常就会抛给上一级
- 处理重定向等问题3XX,307 会从头部获取新的路径,生成一个新的请求
2. BridgeInterceptor
普通的拦截器,加统一的请求头等Content-Type Connection Content-Length Cookie
处理返回的结果,数据压缩用ZipSource,保存Cookie
3. CacheInterceptor
缓存拦截器,在缓存可用的情况下,读取本地缓存数据,如果没有缓存,请求服务器
先判断有没有缓存策略,拿到缓存过期时间,如果缓存过期了需要加一些头部信息
如果后台返回304,表示可以用缓存,每次拿到结果后做缓存处理
307 重定向 Location
4. ConnectInterceptor
连接拦截器
findHealthyConnection()会去缓存池里查找可用的连接,无可用就创建新的
OkHttp 是基于原生的 Socket + OkIO封装
5. CallServerInterceptor
写和读取数据
拦截器执行顺序
看源码就知道执行顺序是
retryAndFollowUpInterceptor-》BridgeInterceptor-》CacheInterceptor-》ConnectInterceptor-》CallServerInterceptor
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}
但是看上面这段源码发现好像并不是只有这五种对吧!
有两句代码,分别是addAll方法,添加了两个集合,集合存储的是啥?
这里其实是自定义拦截器,可以看到,自定义拦截器添加的顺序分别又有两种
根据顺序分别叫做:Application Interceptors和Network Interceptors
集合嘛,也就是说我们可以添加多个自定义拦截器,自由发挥,实现各种需求
okhttp GitHub关于拦截器的介绍
链接:https://github.com/square/okhttp/wiki/Interceptors
//添加Application Interceptors
interceptors.addAll(client.interceptors());
...
//添加Network Interceptors
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
官方拦截器示意图
注册Application Interceptors
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new XXXInterceptor())
.build();
注册Network Interceptors
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new XXXInterceptor())
.build();
OkHttpClient的源码,可以看到定义了两个集合来存储我们注册的自定义拦截器
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
...
final List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors;
final List<Interceptor> networkInterceptors;
public Builder addNetworkInterceptor(Interceptor interceptor) {
if (interceptor == null) throw new IllegalArgumentException("interceptor == null");
networkInterceptors.add(interceptor);
return this;
}
public Builder addInterceptor(Interceptor interceptor) {
if (interceptor == null) throw new IllegalArgumentException("interceptor == null");
interceptors.add(interceptor);
return this;
}
}