首先套用官网的一句话来描述拦截器的作用:
Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.
拦截器是一个功能强大的机制,可以监视、重写和重试调用。
我们首先总结一下okhttp默认添加的几个拦截器的作用
1、RetryAndFollowUpInterceptor:重试和followup拦截器
followup就是跟进的意思
这个拦截器的作用是负责请求的重定向,当一个请求由于各种原因失败了,如果是因为路由或者连接异常导致的则尝试请求恢复连接,如果是因为响应码导致的失败则会重新发起一次请求,比如返回了3xx、307、407等就会重新发起一次请求。同时这个拦截器负责管理okhttp的连接池的复用以及请求完成后释放连接的操作。多路复用的是http2的特性,而okhttp是支持http2的。
2、BridgeInterceptor:桥接拦截器
处理请求体和响应体,把用户构造的请求转换成发送给服务器的请求,把服务器返回的响应体处理成对用户友好的返回值。
1、对请求体的处理主要是添加一些请求头,比如添加User-Agent、Content-Type、Content-Length、Keep-Alive以及如果设置了cookieJar当Cookie为空的时候创建Cookie等
2、对响应体的处理主要是将返回的数据进行gzip解压,去掉一些头信息比如Content-Encoding、Content-Length以及如果设置了cookieJar则保存Cookie等
3、CacheInterceptor:缓存拦截器
首先http的缓存分成强制缓存和对比缓存两种,强制缓存就是当本地缓存有效的时候使用本地缓存,不再发起网络请求,对比缓存就是总会发起网络请求,如果请求的结果和上一次一样那么就返回304,但是不会返回响应体,这个时候就要从本地缓存中取数据,如果请求结果和上一次不一样,那么就会返回新的数据。
所以okhttp的缓存也是从这两个方面来进行的
1、首先判断本地是否有缓存,如果有再判断是否有缓存策略,缓存是否过期,如果没有过期那么就直接使用本地缓存,如果过期了就请求网络
2、如果服务器返回了304那么还是会继续使用本地缓存,如果没有返回304则使用服务器返回的新数据并把它加入到缓存里去
4、ConnectInterceptor 连接拦截器
/** Opens a connection to the target server and proceeds to the next interceptor. */
public final class ConnectInterceptor implements Interceptor {
public final OkHttpClient client;
public ConnectInterceptor(OkHttpClient client) {
this.client = client;
}
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
Transmitter transmitter = realChain.transmitter();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);
return realChain.proceed(request, transmitter, exchange);
}
}
创建和服务器的连接,并执行下一个拦截器,下一个拦截器也就是CallServerInterceptor请求拦截器
5、CallServerInterceptor 请求拦截器
负责网络连接的最后一步,发起网络请求进行数据交换。
主要做了如下几件事:
1、写入header,如果请求头是100-continue那么就只发送请求头询问服务器是否同意接受数据,然后根据后台的返回值判断是否继续发送数据给服务器。如果判断服务器同意接受数据再写入请求体并发起请求。
2、写入请求体,使用的是okio进行操作,okio是okhttp对io操作的一层封装。
3、写入完成后完成请求
4、得到响应体
5、返回响应体
以上就是okhttp的几个默认添加的拦截器的作用啦
另外okhttp遍历默认拦截器和用户自定义拦截器的核心方法是RealInterceptorChain的proceed方法
其核心代码是这几句:
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
1、构建新的RealInterceptorChain对象的时候index值加1,也就是在List interceptors;这个List中取出下一个拦截器来构建一个新的RealInterceptorChain对象,并把这个RealInterceptorChain对象传递给当前拦截器的拦截方法interceptor.intercept(next)
2、执行当前拦截器拦截方法,执行完成后会调用传进来的RealInterceptorChain对象的proceed方法
3、在RealInterceptorChain的proceed方法中又会重复执行上述1步骤。
4、这样就达到了遍历拦截器的目的,其实这是一个责任链模式,每个拦截器负责完成自己的任务,并把责任传递给下一个拦截器。