OkHttp_3.12.0源碼分析
基于OkHttp:3.12.0:https://github.com/square/okhttp/tree/okhttp_3.12.x
RTFSC
Read The Fucking Source Code
流程分析
- 用戶層面調(diào)用形式:
OkHttpClient#newCall(new Request())#enquenue(new Callback(){})
-
OkHttpClient#newCall(new Request()):OkHttpClient根據(jù)client、request創(chuàng)建RealCall,RealCall里面包含所有請(qǐng)求的各種配置信息:攔截器、請(qǐng)求連接、調(diào)度器Dispatcher、ConnectionPool等
//OkHttpClient
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
-
RealCall#enqueue(new Callback(){}):- 通過(guò)RealCall中的client間接獲取Dispatcher--維護(hù)一個(gè)線程池、readyAsyncCalls、runningAsyncCalls、runningSyncCalls三個(gè)請(qǐng)求隊(duì)列。
- Dispatcher的enqueue會(huì)把當(dāng)前的responseCallback包裝成AsyncCall的形式放入readyAsyncCalls隊(duì)列中,注意AsyncCall實(shí)現(xiàn)了Runnable接口。
//RealCall
@Override public void enqueue(Callback responseCallback) {
//其它信息...
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
// Dispatcher
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
}
promoteAndExecute();
}
- Dispatcher#promoteAndExecute:這一步會(huì)遍歷readyAsyncCalls把準(zhǔn)備隊(duì)列中的AsyncCall放到runningAsyncCalls運(yùn)行隊(duì)列中;同時(shí)放到立馬執(zhí)行的一個(gè)列表中:executableCalls。這里一些額外的判斷是:,請(qǐng)求是否超過(guò)了最大請(qǐng)求數(shù)maxRequests,同一個(gè)host是否大于maxRequestsPerHostmaxRequests。
//Dispatcher
private boolean promoteAndExecute() {
//...
List<AsyncCall> executableCalls = new ArrayList<>();
//偽代碼...
if(滿足一定條件){executableCalls.addAll(readyAsyncCalls)}
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
return isRunning;
}
-
AsyncCall#executeOn(executorService()):- AsyncCall#executeOn(ExecutorService):通過(guò)線程池執(zhí)行當(dāng)前對(duì)象,會(huì)調(diào)用上層NamedRunnable的run()方法。重點(diǎn):這里完成線程切換邏輯,因?yàn)橄旅婢鸵_始去執(zhí)行耗時(shí)操作。
- NamedRunnable#run方法會(huì)調(diào)用execute(),具體邏輯在子類AsyncCall實(shí)現(xiàn)。
- AsyncCall#execute()是真正獲取Response值、把值回調(diào)給responseCallback的步驟。
//AsyncCall
void executeOn(ExecutorService executorService) {
//...
executorService.execute(this);//這里會(huì)調(diào)用父類的run方法
//...
}
//NamedRunnable, AsyncCall的父類
public abstract class NamedRunnable implements Runnable {
//...
@Override public final void run() {
//...
execute();
}
//子類AsyncCall做對(duì)應(yīng)實(shí)現(xiàn)
protected abstract void execute();
}
#AsyncCall
@Override protected void execute() {
boolean signalledCallback = false;
timeout.enter();
try {
//關(guān)鍵,去獲取response對(duì)象,真正的耗時(shí)也就在這
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
//失敗,請(qǐng)求被取消
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
//成功請(qǐng)求,拿去結(jié)果回調(diào)
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);
//失敗,回調(diào)
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//完整結(jié)束當(dāng)前請(qǐng)求,做一些收尾操作
client.dispatcher().finished(this);
}
}
}
-
RealCall#getResponseWithInterceptorChain:- RealCall#getResponseWithInterceptorChain會(huì)把用戶自定義的攔截器、系統(tǒng)級(jí)別的攔截器放到list中組裝好,給一個(gè)new RealInterceptorChain。這里需要注意攔截器加入的順序,用戶攔截器優(yōu)先級(jí)最高->系統(tǒng)一些中間攔截->最后網(wǎng)絡(luò)請(qǐng)求。
- RealInterceptorChain#proceed在這里會(huì)構(gòu)造一個(gè)新的RealInterceptorChain:next,注意新的RealInterceptorChain中index+1;另外根據(jù)當(dāng)前的index取得當(dāng)前攔截器,執(zhí)行攔截器中唯一的方法intercept(next),具體執(zhí)行的哪一個(gè)呢,就看上層實(shí)現(xiàn)的是哪一個(gè)具體實(shí)現(xiàn)。
- 我們隨便看一個(gè)實(shí)現(xiàn),假如BridgeInterceptor:會(huì)在BridgeInterceptor中執(zhí)行BridgeInterceptor相關(guān)的實(shí)現(xiàn),最關(guān)鍵的會(huì)執(zhí)行
chain.proceed(requestBuilder.build()),注意Chain是上一個(gè)創(chuàng)建的RealInterceptorChain,所以又跑到了第二步,同時(shí)index這個(gè)時(shí)候已經(jīng)+1,如此完成遞歸操作! - 經(jīng)過(guò)2、3兩步,通過(guò)迭代操作,完整所有攔截器的執(zhí)行。至于說(shuō)網(wǎng)絡(luò)請(qǐng)求、緩存、重試、日志等等核心包括外圍功能,全部通過(guò)攔截器實(shí)現(xiàn),并且責(zé)任分明,高度解耦合,實(shí)現(xiàn)方式:責(zé)任鏈模式。
#RealCall
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));
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);
}
#RealInterceptorChain
@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 {
//...
//注意這里又構(gòu)造了一個(gè)RealInterceptorChain,重點(diǎn)index+1
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
//取當(dāng)前index對(duì)應(yīng)的攔截器
Interceptor interceptor = interceptors.get(index);
//執(zhí)行取到的攔截器
Response response = interceptor.intercept(next);
//...
return response;
}
# BridgeInterceptor
@Override public Response intercept(Chain chain) throws IOException {
//根據(jù)上游chain繼續(xù)處理當(dāng)前攔截器。注意:chain的源頭:RealInterceptorChain#proceed中創(chuàng)建的next,一個(gè)新的RealInterceptorChain
Request userRequest = chain.request();
Request.Builder requestBuilder = userRequest.newBuilder();
//各種邏輯,跳過(guò)只看核心...
//核心,這里又回到了RealInterceptorChain#proceed
Response networkResponse = chain.proceed(requestBuilder.build());
//后續(xù)邏輯...
return responseBuilder.build();
}