目錄
1.OkHttp關鍵類和類的作用
1.1.OkHttpClient(請求用戶端)
1.2.Request
1.3.RealCall
1.4執行請求相關類
1.5.Dispatcher
1.7.BridgeInterceptor
1.8.CacheInterceptor
1.9.ConnectInterceptor
1.10.CallServerInterceptor
2.攔截的調用順序
1.OkHttp關鍵類和類的作用
1.1.OkHttpClient(請求用戶端)
OkHttpClient是用于生産Call {@linkplain Call calls}的工廠,可以發送請求和讀取請求傳回的響應資訊;
a.OkHttpClients應該被公用的
當我們建立一個{@code OkHttpClient}執行個體時并且複用它為了所有的HTTP請求調用時将是更高效的。這是因為彼此用戶端都擁有自己的連接配接池和線程池。複用連接配接和線程将減少延遲并節省記憶體。相反,為每一個請求都建立用戶端将是浪費資源。使用{@code new OkHttpClient()}建立一個有預設配置公用的執行個體,代碼如下;
{@code
// The singleton HTTP client.
public final OkHttpClient client = new OkHttpClient();
}
或者使用 {@code new OkHttpClient.Builder()}去建立一個有定制配置的公用的執行個體,代碼如下;
{@code
// The singleton HTTP client.
public final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor())
.cache(new Cache(cacheDir, cacheSize))
.build();
}
b.使用newBuilder()定制你的用戶端
你能使用{@link #newBuilder()}定制一個共享的OkHttpClient的執行個體。這個将建立一個共享相同連接配接池,線程池和配置的用戶端。使用builder方法去配置為了特殊用途的派生用戶端。這個展示一個500毫秒逾時的調用例子:
{@code
OkHttpClient eagerClient = client.newBuilder()//判斷出來的用戶端-共享連接配接池,線程池等
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();
Response response = eagerClient.newCall(request).execute();
}
c.關閉連接配接或者線程池不是必須的
如果它們保持空閑的,線程和連接配接将被自動釋放。但是,如果您正在編寫一個需要積極釋放未使用的資源的應用程式,您可以這樣做。
關閉dispatcher的線程池服務使用{@link ExecutorService#shutdown shutdown()}。這也會導緻将來客戶被拒絕的調用。
{@code
client.dispatcher().executorService().shutdown();
}
d.使用{@link ConnectionPool#evictAll() evictAll()}清理連接配接池。注意,那個連接配接池的背景線程不能立即退出。
{@code
client.connectionPool().evictAll();
}
e.如果你的用戶端有一個緩存,調用 {@link Cache#close close()}。注意去建立一個被關閉的緩存的調用将是錯誤的,并且這樣将引起崩潰。
{@code
client.cache().close();
}
f.OkHttp為了HTTP/2連接配接也使用背景線程。如果它們空閑,這些連接配接将自動退出
1.2.Request
包裝的一個HTTP請求,如果body是null或者它自己不可變,類的執行個體也是不可變的;
//包含請求的如下資訊
private final HttpUrl url;//請求的url
private final String method;//請求的方法
private final Headers headers;//請求頭
private final RequestBody body;//請求的body
private final Object tag;//請求的标記
1.3.RealCall
RealCall是一個封裝已經準備去執行的請求的調用。這個調用可以被取消。作為這個對象表示單個請求/響應對(流),不能執行兩次。
1.4執行請求相關類
調用RealCall的execute()執行請求時,檢視下面RealCall類中請求的方法如下:
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
我們會看到具體執行網絡請求關鍵步驟類的部分,主要有Dispatcher類和RealCall類下getResponseWithInterceptorChain()方法下關鍵的攔截器類
private 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 (!retryAndFollowUpInterceptor.isForWebSocket()) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(
retryAndFollowUpInterceptor.isForWebSocket()));
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}
RetryAndFollowUpInterceptor,BridgeInterceptor,CacheInterceptor,ConnectInterceptor,CallServerInterceptor。
1.5.Dispatcher
每個Dispatcher使用一個{@ Link ExecutorService }在内部運作調用。如果你提供你的自己的executor,它應該能夠運作 {@linkplain #getMaxRequests 配置的最大}數量的并發調用。
1.6.RetryAndFollowUpInterceptor
這個攔截器可以從請求失敗和重定向中按需要恢複。 它可能抛出異常 {@link IOException} 如何調用被取消。
1.7.BridgeInterceptor
從應用程式代碼到網絡代碼的橋梁。首先,它從使用者請求建立網絡請求,然後繼續調用網絡請求。最後,根據網絡響應建立使用者響應。
1.8.CacheInterceptor
服務緩存中的請求并向緩存寫入響應。
1.9.ConnectInterceptor
打開到目标伺服器的連接配接,并執行下一個攔截器。
1.10.CallServerInterceptor
這是最後一個攔截器,它将調用一個到伺服器的網絡請求。
2.攔截的調用順序
