几个关键的类: intercept接口,RealInterceptorChain责任链,RealCall 发起请求,CallServerInterceptor真正请求网络的类
先看看 okhttp 的请求流程
- 创建 请求对象Call
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false );
}
- 调用execute 执行请求 并 返回 Response对象
@Override protected void execute() {
Response response = getResponseWithInterceptorChain();
}
以上只展示最关键的代码, execute() 通过getResponseWithInterceptorChain方法获得Response 返回结果. 让我们看看这个方法里做了什么事情.
- 添加拦截器 并调用 chain.proceed 方法
Response getResponseWithInterceptorChain() throws IOException {
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));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
这里需要说明一下,首先会创建一个interceptors的集合,这里包含了所有的拦截器,包括开发者自定义的拦截器以及okhttp自带的五大拦截器.注意添加的顺序,自定义拦截器会首先被加入到集合中,然后才是系统自带的拦截器.最后一个拦截器是CallServerInterceptor,它是真正处理网络请求的拦截器.
接下来会创建Interceptor.Chain对象,把添加后的拦截器集合,原始请求,监听器,配置属性作为参数,传入到Chain对象中.
最后执行chain.proceed(originalRequest).
4.核心方法 chain.proceed
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
}
这是最核心的方法, index表示当前方法拦截器的在拦截器集合中的下标, interceptors会取出集合的下个拦截器,并调用它的intercept方法.
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
以上两句代码是okhttp责任链模式的本质. intercept方法会调用的chain.proceed,chain.proceed又调用责任链中的下一个拦截器的intercept方法.这是一个递归的调用.
- interceptor.intercept(Chain chain)
public class HeaderParamInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
builder.addHeader("token", TokenInvalidInterceptor.getToken());
builder.addHeader("clientId", "12345678");
builder.addHeader("requestId", UUID.randomUUID().toString().replace("-", "").toLowerCase());
return chain.proceed(builder.build());
}
}
以自定义HeaderParamInterceptor为例,在方法里先执行业务操作,比如这是给request请求添加header公共参数,最后执行chain.proceed方法,根据我们之前的分析,request请求会交给拦截器集合中的下一个拦截器处理.这个取决我们添加拦截器的顺序.最后一个拦截器是真正请求网络的拦截器.
6.CallServerInterceptor
public final class CallServerInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
HttpCodec httpCodec = realChain.httpStream();
StreamAllocation streamAllocation = realChain.streamAllocation();
RealConnection connection = (RealConnection) realChain.connection();
Request request = realChain.request();
long sentRequestMillis = System.currentTimeMillis();
realChain.eventListener().requestHeadersStart(realChain.call());
httpCodec.writeRequestHeaders(request);
realChain.eventListener().requestHeadersEnd(realChain.call(), request);
... 省略一部分逻辑 ...
request.body().writeTo(bufferedRequestBody);
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
... 省略一部分逻辑 ...
return response;
}
毫无疑问,这是最后发起请求网络并得到服务器返回Reponse对象的地方,不用过多得纠结其内部的逻辑细节.可以很清晰地看出这里在做http请求的封装处理.并通过发起网络请求得到了最终的Response对象.我们可以确定这是一个发生在子线程的阻塞方法.
其他的拦截器在Interceptor方法的最后一行返回chain.proceed(request),但是CallServerInterceptor是直接返回Response对象,这是递归的终点.
然后每个拦截器按照拦截器集合添加的顺序,由后往前依次返回Reponse对象,我们对参数的处理也是在这个过程中,最典型的就是使用自定义拦截器,根据服务器返回的code的不同,来处理失效的token.
最后,我们可以总结出以下的结论:
一. 每个拦截器都有intercept方法,我们可以从RealCall的getResponseWithInterceptorChain方法里找到interceptors集合添加拦截器的顺序:
- 自定义拦截器
- okhttp四大拦截器(retryAndFollowUpInterceptor,BridgeInterceptor,CacheInterceptor,ConnectInterceptor),
- 如果有网络的情况下,会添加networkInterceptors
- 最后调用真正的请求网络的拦截器 CallServerInterceptor.
二. 拦截器集合会被传入到RealInterceptorChain中去. 在proceed方法里,会执行
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
每次调用chain.proceed, interceptors的index都会加一,这样Response response = interceptor.intercept(next) 就成为了递归调用,最后由CallServerInterceptor的intercept方法返回Response结果.
三. 在任何一个拦截器的intercept方法中,修改Request请求参数都必须在chain.proceed之前操作,修改Reponse返回结果必须在chain.proceed方法之后操作.chain.proceed一旦有返回结果就代表网络请求结果返回了.