源代码
GitHub源代码
本文目标
理解okhttp的拦截器各自的作用
拦截器
在发起请求的时候,当执行到execute()方法会调用
Response result = getResponseWithInterceptorChain();
这行代码,就是通过责任链模式的拦截器拿到响应的,具体代码如下
final class RealCall implements Call {
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
// 拦截器的一个集合
List<Interceptor> interceptors = new ArrayList<>();
// 客户端的所有自定义拦截器
interceptors.addAll(client.interceptors());// 自己的
// OKhttp 5 个拦截器 ,责任链设计模式,每一个拦截器只处理与他相关的部分
interceptors.add(retryAndFollowUpInterceptor);// 重试
interceptors.add(new BridgeInterceptor(client.cookieJar()));// 基础
interceptors.add(new CacheInterceptor(client.internalCache()));// 缓存
interceptors.add(new ConnectInterceptor(client));// 建立连接
interceptors.add(new CallServerInterceptor(forWebSocket));// 写数据
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
}
我们自己也可以实现 Interceptor 接口来自定义拦截器,okhttp会先将我们的拦截器添加到集合中,下面的5个拦截器都是okhttp自带的拦截器
1.RetryAndFollowUpInterceptor
处理重试的一个拦截器,会去处理一些异常,只要不是致命的异常就会重新发起一次请求(把Request给下级),如果是致命的异常就会抛给上一级;
会处理一些重定向等等,比如3XX 307,407就会从头部中获取新的路径,生成一个新的请求交给下一级(重新发送一次请求)
2.BridgeInterceptor
做一个简单的处理,设置一些通用的请求头,Content-Type,Connection,Content-Length,Cookie
做一些返回的处理,如果返回的数据被压缩了采用 ZipSource,保存Cookie
3.CacheInterceptor
在缓存可用的情况下,读取本地的缓存的数据,如果没有直接去服务器,如果有首先判断有没有缓存策略,然后判断有没有过期,如果没有过期直接拿缓存,如果过期了需要添加一些之前头部信息如:If-Modified-Since,这个时候后台有可能会给你返回 304 代表你是可以拿本地缓存,每次读取到新的响应后做一次缓存
4.ConnectInterceptor
findHealthyConnection()找一个连接,首先判断有没有健康的,没有就创建(建立Socket,握手连接),连接缓存
okHttp是基于原生的 Socket + okio (原生IO的封装)
封装 HttpCodec 里面封装了okio的 Source(输入) 和 Sink(输出),我们通过 HttpCodec 就可以操作 Socket的输入输出,我们就可以向服务器写数据和读取返回数据
5.CallServerInterceptor
写数据和读取数据
写头部信息,写body表达信息等等
连接的三个核心类
- RealConnection 建立连接的一个对象的封装
- ConnectionPool 保存了连接
- StreamAllocation 找一些链接,做一下封装
网友评论