Okhttp的浅层架构分析
Okhttp的责任链模式和拦截器分析
Okhttp之RetryAndFollowUpInterceptor拦截器分析
Okhttp之BridgeInterceptor拦截器分析
Okhttp之CacheInterceptor拦截器分析
Okhttp之ConnectInterceptor拦截器分析
Okhttp之网络连接相关三大类RealConnection、ConnectionPool、StreamAllocation
上篇大概梳理了一下okhttp的线程调用流程,这次接着看看它真正的网络请求步骤,也就是责任链模式和拦截器相关的知识。接着上篇的终点:
//最终的请求提交,可以看到getResponseWithInterceptorChain()方法拿到response ,这就是开始了责任链调用模式,后面详细分析
@Override
protected void execute() {
boolean signalledCallback = false;
timeout.enter();
try {
//开启责任链调用
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
//取消了请求,调用回调接口的onFailure()方法
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
//拿到了response数据,调用回调接口的onResponse()方法
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
e = timeoutExit(e);
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
开启责任链的方法getResponseWithInterceptorChain():
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());//开发者自定义的拦截器
interceptors.add(retryAndFollowUpInterceptor);//请求重试拦截器
interceptors.add(new BridgeInterceptor(client.cookieJar()));//负责将用户请求转换为网络请求
interceptors.add(new CacheInterceptor(client.internalCache()));//缓存相关
interceptors.add(new ConnectInterceptor(client));//负责链接网络,socket相关
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());//对响应体进行第一时间处理,开发者自定义
}
interceptors.add(new CallServerInterceptor(forWebSocket));//负责读写数据
//将所有要用到的拦截器封装在这个新建的RealInterceptorChain里面
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
//并调用它的proceed()方法,开启责任链调用,这个方法会把每个拦截器的process执行一遍,层层传递下去
return chain.proceed(originalRequest);
}
我们先来研究它的责任链是怎么串起来的,先看看Interceptor接口:
//Interceptor 接口,所有的拦截器都要实现它,并重写intercept(Chain chain)方法
public interface Interceptor {
//就是靠着这个方法一个一个拦截器传递下去
Response intercept(Chain chain) throws IOException;
//内部接口,意义如其名,链条,起到连接每个拦截器 的作用
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
...省略无关代码
}
}
再看看Chain 的实现类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;
@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 {
calls++;
// 又new了一个RealInterceptorChain ,index +1,而且把所有的数据都传给它
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
//取出当前的拦截器,即第一个拦截器
Interceptor interceptor = interceptors.get(index);
//调用他的intercept()方法,并把刚刚创建的RealInterceptorChain 传给它
Response response = interceptor.intercept(next);
...省略旁支代码
return response;
}
}
现在我们来看看官方的第一个拦截器retryAndFollowUpInterceptor干了什么,以及他是怎么把下一个拦截器调动起来的,这里重点分析责任链的流转机制,不对拦截器具体功能分析:
public final class RetryAndFollowUpInterceptor implements Interceptor {
/**
* How many redirects and auth challenges should we attempt? Chrome follows 21 redirects; Firefox,
* curl, and wget follow 20; Safari follows 16; and HTTP/1.0 recommends 5.
*/
private static final int MAX_FOLLOW_UPS = 20;
private final OkHttpClient client;
private final boolean forWebSocket;
private volatile StreamAllocation streamAllocation;
private Object callStackTrace;
private volatile boolean canceled;
@Override public Response intercept(Chain chain) throws IOException {
//从chain里拿到request
Request request = chain.request();
//强转成RealInterceptorChain
RealInterceptorChain realChain = (RealInterceptorChain) chain;
while (true) {
...省略
//看到了调用了realChain的proceed()
response = realChain.proceed(request, streamAllocation, null, null);
...省略
}
}
看到RetryAndFollowUpInterceptor的intercept(Chain chain) 方法就是拿出request进行处理,然后继续调用RealInterceptorChain 的proceed()方法,这个方法在上面分析过了,它会new一个新的RealInterceptorChain 然后拿出下一个拦截器执行它的intercept(Chain chain)方法,就这样一直传递到最后的CallServerInterceptor拦截器,这个拦截器最终会返回一个response,然后顺着之前的拦截器再把这个response往上传,从而让整个责任链都串联起来,而链条正是RealInterceptorChain。
用图来描述一下:
![](https://img.haomeiwen.com/i4045300/b5a8062d9a9f7b11.png)
网友评论