Okhttp解析—Interceptor详解
Interceptor可以说是okhttp的精髓之一,Okhttp重写请求/响应、重试、缓存响应等操作,基本都是在各个Interceptor中完成的,上篇文章分析Okhttp运行流程时只是简单带过,那么这篇文章就来详细分析下Interceptor以及拦截器链机制。
一、Interceptor以及InterceptorChain
/**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding
* responses coming back in. Typically interceptors add, remove, or transform headers on the request
* or response.
*/
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
/**
* Returns the connection the request will be executed on. This is only available in the chains
* of network interceptors; for application interceptors this is always null.
*/
@Nullable Connection connection();
Call call();
int connectTimeoutMillis();
Chain withConnectTimeout(int timeout, TimeUnit unit);
int readTimeoutMillis();
Chain withReadTimeout(int timeout, TimeUnit unit);
int writeTimeoutMillis();
Chain withWriteTimeout(int timeout, TimeUnit unit);
}
}
Interceptor最主要的就是其intercept()函数,InterceptorChain则是Interceptor一个内部类,它的主要作用就是链式有序调用Interceptor。
Okhttp内置了5种Interceptor它们分别是RetryAndFollowUpInterceptor
、BridgeInterceptor、CacheInterceptor、ConnectInterceptor
、CallServerInterceptor。正是这5种Interceptor完成了重写、重试、缓存、请求等操作,接下来我们来逐一分析它们的作用。
二、Interceptor链式调用
拦截器调用的入口是在ReallCall的getResponseWithInterceptorChain()函数中。
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(new RetryAndFollowUpInterceptor(client));
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, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());//1
boolean calledNoMoreExchanges = false;
try {
Response response = chain.proceed(originalRequest);//2
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}
我们看到该函数一开始就构造了一个List然后向里边添加所有的Interceptor,包括我们自定义的Application Interceptor、系统预置的Interceptor、自定义的Network Interceptor等。
然后在注释1处构造RealInterceptorChain实例并传入刚刚的interceptor list还有就是我们看到第四个参数此处传入的是0。该参数表示接下来要调用interceptor list中哪个interceptor。
最后在注释2处调用chain.proceed()并传入原始请求。
@Override public Response proceed(Request request) throws IOException {
return proceed(request, transmitter, exchange);
}
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.exchange != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);//1
Interceptor interceptor = interceptors.get(index);//2
Response response = interceptor.intercept(next);//3
// Confirm that the next interceptor made its required call to chain.proceed().
if (exchange != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
proceed函数我们主要关注3个注释处的操作。
在注释1处构造RealInterceptorChain,其中参数4此时变为index+1,index就是之前在getResponseWithInterceptorChain中构造RealInterceptorChain时传入的值。
注释2处通过index从Interceptor list中取出对应的Interceptor。
注释3处调用Interceptor的intercept()方法,参数传入注释1处构造的RealInterceptorChain。因为Interceptor的操作都是在intercept()函数中完成的,所以该操作完成了当前Interceptor的调用。同时在每个Interceptor的intercept()函数中都会调用next.proceed()这样就开启了下一个Interceptor调用,如此反复最终像链条一样依次调用Interceptor list中所有的Interceptor。
三、详解各个Interceptor
上边我们分析了Interceptor是按顺序调用的,这里的顺序指的是添加到Intercept