包含两个方面的内容,一是网络连接角度发挥作用的网络拦截器,二是从连接池的操作角度发挥作用的拦截器。
1、网络连接拦截器,ConnectInterceptor.java的代码很少,逻辑比较简单:
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();
StreamAllocation streamAllocation = realChain.streamAllocation();
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
}
分析入口依然是我们最熟悉的地方:intercept();该方法的前三行分别创建了三个对象。这里我们重点关注StreamAllocation.
StreamAllocation的作用:用来建立执行OKHttp请求所需要的网络参数组件,分配Stream。
前面在RetryAndFollowUpInterceptor重定向拦截器里面我们家提到过,StreamAllocation在哪里被创建出来,但是真正的使用是在ConnectInterceptor里面,这不,现在我们就在分析这块了。
StreamAllocation对象创建完成后,我们通过下面这段代码进行使用:
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
这里httpCodec对象是用来编码我们的Request和解码我们的response对象的。
RealConnection connection = streamAllocation.connection();
上面这行代码中RealConnection对象的作用——用来进行实际上的网络IO传输。
最后再通过realChain.proceed()来进行来节气的调用。
总结:
1、ConnectInterceptor获取从RetryAndFollowUpInterceptor重定向拦截器传过来的StreamAllocation对象,然后创建HttpCodec对象和RealConnection对象。
HttpCodec对象主要用于编码我们的Request和解码我们的response对象;RealConnection对象用来进行实际上的网络IO传输。
2、调用realChain.proceed()方法将我们刚刚创建的用于编码我们的Request和解码我们的response对象的HttpCodec对象和
用来进行实际上的网络IO传输的RealConnection对象传递给下一个拦截器CallServerInterceptor。
在前面的源码中,有一个很重要的方法:streamAllocation.newStream()。现在我们再来看看这个方法的具体实现:
public HttpCodec newStream(OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
int connectTimeout = chain.connectTimeoutMillis();
int readTimeout = chain.readTimeoutMillis();
int writeTimeout = chain.writeTimeoutMillis();
int pingIntervalMillis = client.pingIntervalMillis();
boolean connectionRetryEnabled = client.retryOnConnectionFailure();
try {
RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);
synchronized (connectionPool) {
codec = resultCodec;
return resultCodec;
}
} catch (IOException e) {
throw new RouteException(e);
}
}
这个方法代码量很小,前面5行代码都是通过chain获取参数,然后try{}代码块中,创建了RealConnection对象用来进行实际上的网络IO传输;HttpCodec对象用于编码我们的Request和解码我们的response对象。
RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);
总结起来就是:创建RealConnection对象和HttpCodec对象,然后选择连接方式,然后再将对象传递给传递给下一个拦截器CallServerInterceptor。
StreamAllocation.java里面有一个连接池的类:ConnectionPool.java,从名字就可以知道他的作用——连接池。他是StreamAllocation.java的核心,链接的管理和回收就由他来实现。有兴趣的可以深入研究。