攔截器:Okhttp中提供的一種強(qiáng)大的機(jī)制,可以實(shí)現(xiàn)網(wǎng)絡(luò)監(jiān)聽、請(qǐng)求/響應(yīng)重寫、請(qǐng)求失敗重試等功能的實(shí)現(xiàn)(攔截器不區(qū)分異步/同步)
Okhttp不管是異步/同步,在RealCall.java中都會(huì)執(zhí)行Response result = getResponseWithInterceptorChain();
- 同步
RealCall.java
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();//執(zhí)行該方法
.....省略無用代碼
}
- 異步
RealCall.java
@Override public void enqueue(Callback responseCallback) {
...省略無用代碼
client.dispatcher().enqueue(new AsyncCall(responseCallback));//跟到AsyncCall中
}
==============================分割線=========================
AsyncCall.execute();
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();//異步也是執(zhí)行該方法
....省略無用代碼
}
接下來看一下getResponseWithInterceptorChain()具體做了什么操作,源碼如下:
//方法字面意思:得到一個(gè)具有攔截器鏈的響應(yīng)
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));//網(wǎng)絡(luò)連接攔截器
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());
//執(zhí)行RealInterceptorChain.proceed();方法,下面將具體分析
return chain.proceed(originalRequest);
}
上面的getResponseWithInterceptorChain()是通過RealInterceptorChain.proceed();方法得到一個(gè)攔截器鏈,下面具體看一下proceed()方法:
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");
}
// Call the next interceptor in the chain.
// 在這里,得到了 next 下一個(gè)鏈,構(gòu)造函數(shù)中將 index+1
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
//interceptors 就是從構(gòu)造函數(shù)中,得到的List<Interceptpr>
//也就是在RealCall.getResponseWithInterceptorChain();中添加的所有的攔截器
Interceptor interceptor = interceptors.get(index);
//在這里,執(zhí)行攔截器的intercept();方法
//在具體攔截器的intercept()方法中,又會(huì)調(diào)用next chain的proceed();方法
//構(gòu)成了一個(gè)鏈
Response response = interceptor.intercept(next);
....省略部分代碼
return response;
}
proceed()方法執(zhí)行過程大概是:
在內(nèi)部將index+1,得到下一個(gè)RealInterceptorChain,通過具體的攔截器的intercept()方法,繼續(xù)執(zhí)行下一個(gè)鏈的proceed();方法,依次直到最后一個(gè)攔截器,從而形成一個(gè)鏈(有點(diǎn)類似于遞歸,依次往內(nèi)部請(qǐng)求,結(jié)果從最內(nèi)部一層一層傳到最外層)。