前言
Android開發中,常用的第三方網絡請求架構有Retrofit,OKHttp,Volley。最近重構項目架構采用的是Kotlin + Retrofit + RxJava,Retrofit的底層實作就是OKHttp實作。本篇文章介紹OKHttp源碼執行過程。
請求示例
1.Gradle引入
GRADLE
compile 'com.squareup.okhttp3:okhttp:(insert latest version)'
2.GET請求
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
4.OKHttp請求流程

5.源碼執行流程
根據上面的執行流程和GET請求,我們來看下源碼是如何是如何實作的。
OKHttpClient是什麼?
網絡請求的工廠,用于發送HTTP請求并且讀取響應的一個類。通過new OKHttpClient()方式來建立一個單一的HTTP用戶端。我們來分析一波OKHttpClient的源碼。
我們來看下OKHttpClient類的newCall(request)方法做了啥。
/**
* Prepares the {@code request} to be executed at some point in the future.
* 準備request網絡請求 在将來某個時候執行。
*/
@Override public Call newCall(Request request) {
return new RealCall(this, request, false /* for web socket */);
}
網絡請求Request的建構很簡單。我們的Request類中通過建造者(Builder)模式,将請求的Url(請求位址連結),Method(請求方法),Headers(請求頭),Body(請求體)等資訊添加到Request對象中。我們可以看到new Call(request)方法很簡單傳回了RealCall的執行個體。接下來我們進入RealCall類中一探究竟。
RealCall 實作了Call接口,在Call中我們定義了請求方法。
Call接口:
/**
* 請求方法
*/
Request request();
/**
* 同步請求方法
*/
Response execute() throws IOException;
/**
* 異步請求方法
*/
void enqueue(Callback responseCallback);
/**
* 取消請求調用
*/
void cancel();
/**
* 判斷請求調用是否執行
*/
boolean isExecuted();
/**
* 判斷請求調用是否取消
*/
boolean isCanceled();
/**
* 克隆一個請求調用
*/
Call clone();
RealCall.構造函數
RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
final EventListener.Factory eventListenerFactory = client.eventListenerFactory();
//傳入的OKHttpClient對象
this.client = client;
//傳入的Request請求對象
this.originalRequest = originalRequest;
//是否是webSocket請求,這裡預設false
this.forWebSocket = forWebSocket;
//一個可以重故障中恢複的攔截器(出鏡很高-->攔截器)
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
RealCall.excute()
@Override public Response execute() throws IOException {
//1.目前請求已經執行過 抛異常
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
//2.捕獲目前請求堆棧跟蹤變化
captureCallStackTrace();
try {
//3.執行同步網絡請求操作(**Dispatcher分發器是什麼?**)
client.dispatcher().executed(this);
//4.擷取請求傳回的結果
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
//5.結束目前網絡請求
client.dispatcher().finished(this);
}
}
Dispatcher分發器是什麼?
執行異步請求時的政策?通俗點來說,我們有很多的異步請求,請求的執行順序,執行規則都是由分發器決定的,每個分發器的内部有個ThreadPoolExecutor,這是線程池的核心類。作用是什麼呢?當然是将線程進行複用,每個請求需要一個線程去執行,當執行完一個請求任務結束之後,重新建立新的線程太消耗性能。不需要在重新建立一個新的線程去執行下一個任務。我們先有這樣一個概念,Java的線程池是個很”重”的知識點,改天我們将他’扒個幹淨’。接下來我們看下Dispatcher類中的請求方法。
同步:
/** 運作同步調用。包括尚未結束的已取消呼叫 */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
/** 将我們請求添加到同步請求隊列中 */
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
異步:
/** 運作異步調用。包括尚未結束的已取消呼叫 */
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
每一個請求都建立了一個RealCall執行個體,而異步請求AsyncCall 是RealCall的内部類,每個Call都需要一個線程去任務,執行Call的過程其實就是執行線程的excute()過程。當Dispatcher接收到一個請求時,Dispatcher負責在其内部維護的線程池中找出空閑的線程去執行其execute()方法。
Response傳回
RealCall類中執行請求動作後就通過 Response result = getResponseWithInterceptorChain();傳回了服務端響應的結果。
Response getResponseWithInterceptorChain() throws IOException {
// 建立一個完整的攔截器堆棧
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
//1.暫且叫它 -->可恢複的攔截器,根據需要進行重定向
interceptors.add(retryAndFollowUpInterceptor);
//2.橋接攔截器
interceptors.add(new BridgeInterceptor(client.cookieJar()));
//3.請求是從内部緩存中發出,緩存攔截器将傳回寫入到響應緩存中和此請求對應
interceptors.add(new CacheInterceptor(client.internalCache()));
//4.打開用戶端與目标伺服器的連接配接-->連接配接伺服器
interceptors.add(new ConnectInterceptor(client));
//5.攔截器鍊中最後一個攔截器,對伺服器進行請求呼叫
interceptors.add(new CallServerInterceptor(forWebSocket));
//6.Boss是我:承載整個攔截器鍊的具體攔截器鍊:所有應用程式,攔截器、OkHttp核心、所有網絡攔截器,最後是網絡調用者。
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, , originalRequest);
return chain.proceed(originalRequest);
}
核心方法proceed(….)的請求傳回核心代碼如下。
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpCodec, connection, index + , request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
return response;
}
結尾
本篇介紹了OKHttp的源碼執行的流程,下篇将對OKHttp網絡請求究竟發生了什麼?如何得到伺服器傳回值?以及對OKHttp的核心攔截器将會作詳細的介紹。