OkHttp3(九)--RealInterceptorChain
2019-01-28 本文已影响0人
azu_test
RealInterceptorChain
- 拦截器链表存储器,里面存储了所有的拦截器,还有一些网络请求属性
- 每次执行下一个拦截器的拦截事件前都会创建一个新的拦截器链表,用来更新为最新的数据,然后将拦截器链表交付给拦截器,让拦截器去做新的拦截操作,最后返回请求数据。
- 至于怎么让拦截器执行下一个拦截操作使用的是
private final int index;
这个属性值来做鉴别应该取拦截器链表里面的第几个拦截器,然后让其做相应的拦截操作。
RealInterceptorChain关键代码
public final class RealInterceptorChain implements Interceptor.Chain {
//所有的拦截器都存储在这个链表里
private final List<Interceptor> interceptors;
//这个非常重要,将会单独解读处理
private final StreamAllocation streamAllocation;
//这个非常重要,将会单独解读处理
private final HttpCodec httpCodec;
//这个非常重要,将会单独解读处理
private final RealConnection connection;
private final int index;
private final Request request;
private final Call call;
private final EventListener eventListener;
private final int connectTimeout;
private final int readTimeout;
private final int writeTimeout;
private int calls;
//构造方法
public RealInterceptorChain(List<Interceptor> interceptors, StreamAllocation streamAllocation,
HttpCodec httpCodec, RealConnection connection, int index, Request request, Call call,
EventListener eventListener, int connectTimeout, int readTimeout, int writeTimeout) {
this.interceptors = interceptors;
this.connection = connection;
this.streamAllocation = streamAllocation;
this.httpCodec = httpCodec;
this.index = index;
this.request = request;
this.call = call;
this.eventListener = eventListener;
this.connectTimeout = connectTimeout;
this.readTimeout = readTimeout;
this.writeTimeout = writeTimeout;
}
//执行继续拦截操作
@Override public Response proceed(Request request) throws IOException {
return proceed(request, streamAllocation, httpCodec, connection);
}
//执行继续拦截操作
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) 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.httpCodec != null && !this.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.httpCodec != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
//创建新的实例, 并将计数器+1
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
//取出下一个拦截器
Interceptor interceptor = interceptors.get(index);
//执行拦截器方法,拦截器中又会调用proceed()方法
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (httpCodec != 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()
方法将调用拦截器的Interceptor.intercept()
方法,然后这个方法内部会根据条件抛出异常、结果或者继续调用proceed()
方法进行下一项拦截。- 拦截器的顺序
RetryAndFollowUpInterceptor
,BridgeInterceptor
,CacheInterceptor
,ConnectInterceptor
,CallServerInterceptor
。- 还有一些属性对象我们目前不知为什么作用,例如:
StreamAllocation
,HttpCodec
,RealConnection
。我们将根据代码运行流程一步步来解析。
根据上文的方法调用和拦截器的顺序我们可知下面将执行RetryAndFollowUpInterceptor拦截器。