Anroid OKhttp筆記1 流程分析
Android OkhttpInterceptor 筆記:RetryAndFollowUpInterceptor
Android OkhttpInterceptor 筆記:BridgeInterceptor
Android OkhttpInterceptor 筆記:ConnectInterceptor
Android OkhttpInterceptor 筆記:CacheInterceptor
Android OkhttpInterceptor 筆記:CallServerInterceptor
Android Okhttp筆記:ConnectionPool
Android Okhttp3:Dispatcher分析筆記
一、okhttp 內(nèi)置攔截器
本流程都是先創(chuàng)建一個OkHttpClient對象,然后通過Request.Builder()創(chuàng)建一個Request對象,OkHttpClient對象調(diào)用newCall()并傳入Request對象就能獲得一個Call對象。然后獲取一個真正用來進行請求的Call RealCall.execute :
final class RealCall implements Call {
final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
final EventListener.Factory eventListenerFactory = client.eventListenerFactory();
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
// TODO(jwilson): this is unsafe publication and not threadsafe.
this.eventListener = eventListenerFactory.create(this);
}
@Override
public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
try {
//進行網(wǎng)絡(luò)請求
client.dispatcher().executed(this);
//經(jīng)過一層層網(wǎng)絡(luò)攔截器之后,獲取網(wǎng)絡(luò)請求的返回值
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
//Application攔截器
interceptors.addAll(client.interceptors());
//重定向和失敗后重新請求攔截器
interceptors.add(retryAndFollowUpInterceptor);
//網(wǎng)橋攔截器,顧名思義client和Server之前的橋梁
interceptors.add(new BridgeInterceptor(client.cookieJar()));
//緩存處理攔截器
interceptors.add(new CacheInterceptor(client.internalCache()));
//Socket層的握手鏈接
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
//網(wǎng)絡(luò)攔截器
interceptors.addAll(client.networkInterceptors());
}
//client和Server之前的讀寫操作
interceptors.add(new CallServerInterceptor(forWebSocket));
//責(zé)任鏈開始執(zhí)行
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain.proceed(originalRequest);
}
}
okhttp的攔截器就是將整個請求網(wǎng)絡(luò)的過程的每一步都封裝在不同的Interceptor里, 簡單點說就是把一個List里的Interceptor都順序執(zhí)行一遍
重試及重定向攔截器 RetryAndFollowUpInterceptor 負責(zé)請求的重試和重定向
橋接攔截器 BridgeInterceptor 給請求添加對應(yīng)的 header 信息,處理響應(yīng)結(jié)果的 header 信息
緩存攔截器 CacheInterceptor 根據(jù)當(dāng)前獲取的狀態(tài)選擇 網(wǎng)絡(luò)請求 、讀取緩存、更新緩存。
連接攔截器 ConnectInterceptor 建立 http 連接。
讀寫攔截器 CallServerInterceptor 通過連接好的通道進行數(shù)據(jù)的交換;
正常的一個okhttp網(wǎng)絡(luò)請求都走了哪些攔截器:

二、RetryAndFollowUpInterceptor核心代碼
This interceptor recovers from failures and follows redirects as necessary
網(wǎng)絡(luò)請求失敗后,在一些必要的條件下,會重新進行網(wǎng)絡(luò)請求。
大量代碼就不寫了,核心部分
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//...省略部分代碼
StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(request.url()), call, eventListener, callStackTrace);
//...省略部分代碼
while (true) {
Response response;
boolean releaseConnection = true;
try {
response = realChain.proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
throw e.getFirstConnectException();
}
releaseConnection = false;
continue;
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
releaseConnection = false;
continue;
} finally {
// We're throwing an unchecked exception. Release any resources.
if (releaseConnection) {
streamAllocation.streamFailed(null);
streamAllocation.release();
}
}
// Attach the prior response if it exists. Such responses never have a body.
if (priorResponse != null) {
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}
Request followUp;
try {
//判斷是否進行重新請求
followUp = followUpRequest(response, streamAllocation.route());
} catch (IOException e) {
streamAllocation.release();
throw e;
}
if (followUp == null) {
//如果為空,則釋放資源,不空則繼續(xù)下一次請求
streamAllocation.release();
return response;
}
request = followUp;
priorResponse = response;
}
}
三、解讀
1.正常流程
response = realChain.proceed(request, streamAllocation, null, null)
去網(wǎng)絡(luò)獲取到response并傳遞給下一級攔截器,然后沒有其他情況 ,followUpRequest==null 就返回response;
2其他
followUpRequest(response, streamAllocation.route());方法看會不會返回一個新的Request,若返回需要重定向,也就是拿新的Request去獲取Response,當(dāng)然這里有一個最大重定向次數(shù)限制:
private static final int MAX_FOLLOW_UPS = 20;
3.異常情況
當(dāng)發(fā)生RouteException時候,并且 recover為false的時候,這時候會跳出循環(huán),然后拋出去異常,并回調(diào)callback.onFailure(Exception e),返回給UI層進行處理 ,假如說沒有開數(shù)據(jù)流量的情況下,去請求網(wǎng)絡(luò),則會拋出該異常。
第二種:當(dāng)發(fā)生IOException時候,recover為false的時候,則hrow exception,中斷死循環(huán)的操作,
4.recover方法
private boolean recover(IOException e, boolean routeException, Request userRequest) {
streamAllocation.streamFailed(e);
//1.判斷 OkHttpClient 是否支持失敗重連的機制
// The application layer has forbidden retries.
if (!client.retryOnConnectionFailure()) return false;
// 在該方法中傳入的 routeException值 為 true
// We can't send the request body again.
if (!routeException && userRequest.body() instanceof UnrepeatableRequestBody) return false;
//2.isRecoverable 檢測該異常是否是致命的。
// This exception is fatal.
if (!isRecoverable(e, routeException)) return false;
// No more routes to attempt.
//3.是否有更多的路線
if (!streamAllocation.hasMoreRoutes()) return false;
// For failure recovery, use the same route selector with a new connection.
return true;
}
recover 方法主要做了以下幾件事:
1判斷 OkHttpClient 是否支持失敗重連的機制;
如果不支持重連,就表示請求失敗就失敗了,不能再重試了。
2請求Request出錯不能繼續(xù)使用
3.是否可以恢復(fù)的isRecoverable 方法異常檢測
在該方法中會檢測異常是否為嚴重異常,嚴重異常就不要進行重連了,下面檢測的異常都做了注釋。這里涉及到一個
SocketTimeoutException 的異常,表示連接超時異常,這個異常還是可以進行重連的,也就是說OKHTTP 內(nèi)部在連接超時時是會自動進行重連的.
協(xié)議錯誤(ProtocolException)
中斷異常(InterruptedIOException)
SSL握手錯誤(SSLHandshakeException && CertificateException)
certificate pinning錯誤(SSLPeerUnverifiedException)
4.沒用更多線路可供選擇
5..StreamAllocation
StreamAllocation是真正負責(zé)socket連接的,這里又沒有涉及到真正的socket,為什么在這里實例化?這是因為RetryAndFollowUpInterceptor 里面一些情況下是需要釋放連接的,而它又是第一個核心功能攔截器,所以必須在這里實例化,這是為了確保這里能釋放。
Anroid OKhttp筆記1 流程分析
Android OkhttpInterceptor 筆記:RetryAndFollowUpInterceptor
Android OkhttpInterceptor 筆記:BridgeInterceptor
Android OkhttpInterceptor 筆記:ConnectInterceptor
Android OkhttpInterceptor 筆記:CacheInterceptor
Android OkhttpInterceptor 筆記:CallServerInterceptor
Android Okhttp筆記:ConnectionPool
Android Okhttp3:Dispatcher分析筆記