攔截器:Okhttp中提供的一種強(qiáng)大的機(jī)制崖堤,可以實(shí)現(xiàn)網(wǎng)絡(luò)監(jiān)聽(tīng)吗氏、請(qǐng)求/響應(yīng)重寫(xiě)幅垮、請(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í)行該方法
.....省略無(wú)用代碼
}
- 異步
RealCall.java
@Override public void enqueue(Callback responseCallback) {
...省略無(wú)用代碼
client.dispatcher().enqueue(new AsyncCall(responseCallback));//跟到AsyncCall中
}
==============================分割線(xiàn)=========================
AsyncCall.execute();
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();//異步也是執(zhí)行該方法
....省略無(wú)用代碼
}
接下來(lái)看一下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()
是通過(guò)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í)行過(guò)程大概是:
在內(nèi)部將index+1撵割,得到下一個(gè)RealInterceptorChain
贿堰,通過(guò)具體的攔截器的intercept()
方法,繼續(xù)執(zhí)行下一個(gè)鏈的proceed();
方法啡彬,依次直到最后一個(gè)攔截器羹与,從而形成一個(gè)鏈(有點(diǎn)類(lèi)似于遞歸,依次往內(nèi)部請(qǐng)求,結(jié)果從最內(nèi)部一層一層傳到最外層)庶灿。