OkHttp 的依賴
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
OkHttp 的簡單用法
/**
* 創(chuàng)建 Call
*/
private Call newCall() {
// 創(chuàng)建客戶端對象
OkHttpClient client = new OkHttpClient.Builder()
// 設置讀取超時時間
.readTimeout(5, TimeUnit.SECONDS)
.build();
// 創(chuàng)建請求對象
Request request = new Request.Builder().url("https://www.baidu.com").build();
// 創(chuàng)建 Call 對象
Call call = client.newCall(request);
return call;
}
/**
* 同步請求
*/
private void synRequest() {
Call call = newCall();
new Thread() {
@Override
public void run() {
try {
// execute 是 OKHttp 里面的同步請求
Response response = call.execute();
Log.e("young_test", "synRequest result = " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
/**
* 異步請求
*/
private void asyRequest (){
Call call = newCall();
// 將任務壓入隊列中
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e("young_test", "asyRequest result = " + response.body().string());
}
});
}
由簡單用法可以知道,OkHttp 的同步請求和異步請求的主要區(qū)別是調(diào)用方法不同赶舆,其他參數(shù)的構(gòu)建是一樣的砌庄。
OkHttp 涉及的設計模式
- 構(gòu)建者模式(OkHttpClient.Builder封拧、Request.Builder)
- 責任鏈模式(攔截器 RealInterceptorChain)
一、OkHttp 涉及到的類
- OkHttpClient:OKHttp 的客戶端類硫狞,設置請求超時時間信轿、讀取超時時間、攔截器残吩、連接池财忽、分發(fā)器、cookie 等泣侮;
也是 Call即彪、WebSocket 的工廠類;- Request:一個HTTP請求活尊。如果類體為null或其本身不可變隶校,該類的實例就是不可變的。主要類配置請求信息(請求 url蛹锰、請求方法深胳、請求頭、請求體等)宁仔;
- Call:是一個任務接口稠屠,有且只有一個實現(xiàn)類 RealCall峦睡;
- RealCall:Call 的唯一實現(xiàn)類;
- Dispatcher:分發(fā)器权埠,很核心的一個類榨了,主要用來接收同步/異步的請求隊列,并且持有線程池分發(fā)執(zhí)行任務攘蔽;
- ConnectionPool:客戶端和服務器的一個連接龙屉,就是一個 Connection,每個Connection 我們都會放到 ConnectionPool 满俗,由 ConnectionPool 進行統(tǒng)一管理連接转捕,當請求的 url 是相同的,則可以選擇復用唆垃;也會制定一些策略五芝,決定哪些復用,哪些需要關(guān)閉辕万;
二枢步、OkHttp 主要執(zhí)行流程
Okhttp主要流程時序圖
OkHttp發(fā)起請求大概流程圖
三、OkHttp 類解析
- OkHttpClient
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
// 分發(fā)器
final Dispatcher dispatcher;
// 準備在將來某個時刻執(zhí)行的請求
@Override
public Call newCall(Request request) {
// 調(diào)用 RealCall 的靜態(tài)方法newRealCall創(chuàng)建 RealCall
return RealCall.newRealCall(this, request, false /* for web socket */);
}
// 使用請求連接一個新的網(wǎng)絡套接字(WebSocket)
@Override
public WebSocket newWebSocket(Request request, WebSocketListener listener) {
// 創(chuàng)建 RealWebSocket
RealWebSocket webSocket = new RealWebSocket(request, listener, new Random());
// 對 socket 進行連接
webSocket.connect(this);
return webSocket;
}
// OkHttpClient 的構(gòu)建器
public static final class Builder {
// 分發(fā)器
Dispatcher dispatcher;
// 連接池
ConnectionPool connectionPool;
// 構(gòu)造函數(shù)
public Builder() {
// 創(chuàng)建分發(fā)器
dispatcher = new Dispatcher();
// 創(chuàng)建連接池
connectionPool = new ConnectionPool();
}
// 構(gòu)造函數(shù)
Builder(OkHttpClient okHttpClient) {
// 將 OkHttpClient 中的分發(fā)器渐尿,賦值給 Builder 的 dispatcher
this.dispatcher = okHttpClient.dispatcher;
this.connectionPool = okHttpClient.connectionPool;
}
// 構(gòu)建OkHttpClient
public OkHttpClient build() {
return new OkHttpClient(this);
}
}
}
- Call (RealCall)
final class RealCall implements Call {
// 客戶端
final OkHttpClient client;
// 重定向和重試攔截器
final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
// 守衛(wèi)當前類醉途,保證 execute/enqueue 兩者中的一個只能執(zhí)行一次,也就是保證RealCall只能用一次
private boolean executed;
// 構(gòu)造方法私有化
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
...
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
// 用于構(gòu)建 RealCall 對象
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
...
}
// 執(zhí)行同步方法
@Override
public Response execute() throws IOException {
synchronized (this) {
// 用 executed 這個標志砖茸,來保證隘擎,execute/enqueue 只執(zhí)行一次,也就是保證
// 一個 Call 只可以使用一次
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
// 捕獲調(diào)用堆棧跟蹤
captureCallStackTrace();
// 一些網(wǎng)絡回調(diào)操作
eventListener.callStart(this);
try {
// 這句是關(guān)鍵凉夯,將我們需要執(zhí)行的請求(Call)添加到Dispatcher的同步請求隊列中(Dispatcher#runningSyncCalls)
client.dispatcher().executed(this);
// 通過責任鏈方式货葬,啟動請求
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
// 將請求任務添加到 Dispatch 的異步執(zhí)行隊列(Dispatcher#runningAsyncCalls)或 緩存隊列中(Dispatcher#readyAsyncCalls)
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
// 使用攔截鏈(責任鏈)開啟請求
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
// 將我們自定義的攔截器加入到攔截器數(shù)組中
interceptors.addAll(client.interceptors());
// 重定向和重試攔截器
interceptors.add(retryAndFollowUpInterceptor);
// 網(wǎng)絡橋接攔截器
interceptors.add(new BridgeInterceptor(client.cookieJar()));
// 緩存攔截器
interceptors.add(new CacheInterceptor(client.internalCache()));
// 網(wǎng)絡連接攔截器
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
// 非網(wǎng)絡套接字(Socket)的時候,可添加客戶端自定義的網(wǎng)絡攔截器
interceptors.addAll(client.networkInterceptors());
}
// 這是鏈中的最后一個攔截器恍涂。它對服務器進行網(wǎng)絡調(diào)用宝惰。
interceptors.add(new CallServerInterceptor(forWebSocket));
// 創(chuàng)建攔截器鏈
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
// 調(diào)用 proceed 方法執(zhí)行請求
return chain.proceed(originalRequest);
}
// 異步請求任務
final class AsyncCall extends NamedRunnable {
// 異步請求的回調(diào)
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
// 調(diào)用父類構(gòu)造方法,設置線程名稱
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
}
@Override
protected void execute() {
// 這個只是表示是否已經(jīng)執(zhí)行了回調(diào)方法
boolean signalledCallback = false;
try {
// 通過責任鏈方式再沧,啟動請求
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
// 如果重定向攔截器被關(guān)閉尼夺,則表示請求失敗
// 表示已經(jīng)執(zhí)行了回調(diào)方法
signalledCallback = true;
// 回調(diào)失敗方法
responseCallback.onFailure(okhttp3.RealCall.this, new IOException("Canceled"));
} else {
// 表示已經(jīng)執(zhí)行了回調(diào)方法
signalledCallback = true;
// 回調(diào)成功方法
responseCallback.onResponse(okhttp3.RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(okhttp3.RealCall.this, e);
responseCallback.onFailure(okhttp3.RealCall.this, e);
}
} finally {
/*
下面這句代碼做了幾件事
1. 將當前任務從執(zhí)行隊列(Dispatcher#runningAsyncCalls/Dispatcher#runningSyncCalls)移除;
2. 將緩存隊列(Dispatcher#readyAsyncCalls)中的數(shù)據(jù)放到(Dispatcher#runningAsyncCalls)執(zhí)行隊列中(只有異步的時候才執(zhí)行)炒瘸;
3. 重新計算正在執(zhí)行的任務數(shù)(Dispatcher#runningAsyncCalls.size() + Dispatcher#runningSyncCalls.size())
4. 如果正在執(zhí)行的任務數(shù)為 0淤堵,同時空閑任務不為空,則執(zhí)行空閑任務
*/
client.dispatcher().finished(this);
}
}
}
- Dispatcher
public final class Dispatcher {
// 最大請求數(shù)
private int maxRequests = 64;
// 正在運行的每個主機的請求數(shù)
private int maxRequestsPerHost = 5;
// 空閑任務
private @Nullable
Runnable idleCallback;
// 內(nèi)部維護的線程池
private @Nullable
ExecutorService executorService;
// 異步請求任務的緩存隊列
private final Deque<RealCall.AsyncCall> readyAsyncCalls = new ArrayDeque<>();
// 正在運行的/已取消運行的異步請求任務隊列
private final Deque<RealCall.AsyncCall> runningAsyncCalls = new ArrayDeque<>();
// 正在運行的/已取消的同步請求任務隊列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
// 構(gòu)造函數(shù)
public Dispatcher(ExecutorService executorService) {
this.executorService = executorService;
}
// 構(gòu)造函數(shù)
public Dispatcher() {
}
// 創(chuàng)建一個線程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
/*
int corePoolSize:核心線程數(shù)設置為 0顷扩,這樣是為了讓線程快速創(chuàng)建拐邪;
int maximumPoolSize:最大線程數(shù)設置為最大值,這樣是可以無限制的創(chuàng)建線城池隘截;
long keepAliveTime:非核心線程的存活時間扎阶,設置 60 秒汹胃;
TimeUnit unit:非核心線程的存活時間的單位;
BlockingQueue<Runnable> workQueue:線程執(zhí)行任務的緩存隊列东臀,設置 SynchronousQueue 着饥,是一個空隊列,
表示不讓線程池里面做任務的緩存操作惰赋,全部由外面的隊列自己維護宰掉;
ThreadFactory threadFactory:線程池的創(chuàng)建工廠
*/
// corePoolSize、maximumPoolSize赁濒、workQueue 的設置轨奄,可以讓線程高效的創(chuàng)建和復用,可以更高效率的執(zhí)行任務
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
// 異步請求任務的處理
synchronized void enqueue(RealCall.AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
// 如果正在執(zhí)行的異步任務數(shù) < 最大請求任務數(shù)拒炎,同時 正在運行每個主機的請求數(shù) < 最大的正在運行的每個主機的請求數(shù)
// 將任務添加到正在運行的異步請求隊列
runningAsyncCalls.add(call);
// 利用線程池挪拟,執(zhí)行任務
executorService().execute(call);
} else {
// 將任務添加到異步任務緩存隊列中
readyAsyncCalls.add(call);
}
}
// 同步請求任務的處理
synchronized void executed(RealCall call) {
// 將任務添加到同步請求隊列
runningSyncCalls.add(call);
}
// 將異步任務緩存隊列的任務放到正在運行的異步任務隊列中
private void promoteCalls() {
// 正在執(zhí)行的的異步任務隊列數(shù)大于最大的異步任務請求數(shù),則直接返回
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
// 異步任務緩存隊列為空击你,則直接返回
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
// 遍歷異步任務緩存隊列
for (Iterator<RealCall.AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
RealCall.AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
// 如果正在運行的同主機的請求數(shù) < 最大的每個主機的請求數(shù)
// 將任務從異步緩存任務隊列中移除
i.remove();
// 將任務添加到正在執(zhí)行的異步隊列
runningAsyncCalls.add(call);
// 線程池執(zhí)行任務
executorService().execute(call);
}
// 如果正在運行的異步任務隊列 >= 最大的請求數(shù)挥唠,則退出循環(huán)
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
// 返回跟當前執(zhí)行任務的主機相同的正在執(zhí)行的請求數(shù)
private int runningCallsForHost(RealCall.AsyncCall call) {
int result = 0;
// 遍歷正在執(zhí)行的異步請求隊列
for (RealCall.AsyncCall c : runningAsyncCalls) {
// 判斷主機是否跟當前任務的主機一樣
if (c.host().equals(call.host())) result++;
}
return result;
}
}
- 攔截器
- 攔截器核心方法執(zhí)行:proceed -> intercept 愕够,intercept -> proceed
- 1.創(chuàng)建一系列攔截器踩麦,并將其放入一個攔截器list中虹曙;
- 2.創(chuàng)建一個攔截器鏈ReallnterceptorChain,并執(zhí)行攔截器鏈的proceed方法谷誓;
- 3.在發(fā)起請求前對request進行處理绒障;
- 4.調(diào)用下一個攔截器,獲取response捍歪;
- 5.對response進行處理户辱,返回給上一個攔截器;
4.1 RetryAndFollowUpInterceptor - 失敗重連攔截器
- 創(chuàng)建StreamAllocation對象糙臼;
- 調(diào)用ReallnterceptorChain.proceed(...)進行網(wǎng)絡請求庐镐;
- 根據(jù)異常結(jié)果或者響應結(jié)果判斷是否要進行重新請求;
- 調(diào)用下一個攔截器变逃,對response進行處理必逆,返回給上一個攔截器;
public final class RetryAndFollowUpInterceptor implements Interceptor {
// 最大的允許重定向的次數(shù)揽乱,Chrome是21名眉,F(xiàn)irefox、curl和wget 是 20凰棉,Safari是16损拢,HTTP/1.0推薦5
private static final int MAX_FOLLOW_UPS = 20;
// 用來建立和組織http請求所需要的組件的,用來做流分配的
private StreamAllocation streamAllocation;
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Call call = realChain.call();
EventListener eventListener = realChain.eventListener();
// 創(chuàng)建 StreamAllocation
streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(request.url()),
call, eventListener, callStackTrace);
int followUpCount = 0;
Response priorResponse = null;
// 這里之所以用循環(huán)撒犀,是為了防止出現(xiàn)問題的時候福压,跟進結(jié)果判斷是否要進行重新請求
while (true) {
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}
Response response;
boolean releaseConnection = true;
try {
// 調(diào)用攔截鏈的 proceed掏秩,就是調(diào)用下一個攔截器
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(), false, request)) {
throw e.getLastConnectException();
}
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, 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 = followUpRequest(response);
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
return response;
}
closeQuietly(response.body());
if (++followUpCount > MAX_FOLLOW_UPS) {
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (followUp.body() instanceof UnrepeatableRequestBody) {
streamAllocation.release();
throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
if (!sameConnection(response, followUp.url())) {
streamAllocation.release();
streamAllocation = new StreamAllocation(client.connectionPool(),
createAddress(followUp.url()), call, eventListener, callStackTrace);
} else if (streamAllocation.codec() != null) {
throw new IllegalStateException("Closing the body of " + response
+ " didn't close its backing stream. Bad interceptor?");
}
request = followUp;
priorResponse = response;
}
}
}
4.2 BridgeInterceptor- 網(wǎng)絡橋接攔截器
- 是連接復用的基礎;
- 是負責將用戶構(gòu)建的一個Request請求轉(zhuǎn)化為能夠進行網(wǎng)絡訪問的請求荆姆;
- 將這個符合網(wǎng)絡請求的Request進行網(wǎng)絡請求蒙幻;
- 將網(wǎng)絡請求回來的響應 Response轉(zhuǎn)化為用戶可用的Response;
public final class BridgeInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request userRequest = chain.request();
Request.Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
if (body != null) {
MediaType contentType = body.contentType();
if (contentType != null) {
requestBuilder.header("Content-Type", contentType.toString());
}
long contentLength = body.contentLength();
if (contentLength != -1) {
requestBuilder.header("Content-Length", Long.toString(contentLength));
requestBuilder.removeHeader("Transfer-Encoding");
} else {
requestBuilder.header("Transfer-Encoding", "chunked");
requestBuilder.removeHeader("Content-Length");
}
}
if (userRequest.header("Host") == null) {
requestBuilder.header("Host", hostHeader(userRequest.url(), false));
}
if (userRequest.header("Connection") == null) {
// 開啟 Keep-Alive胞枕,就是讓 http 開啟后杆煞,一段時間內(nèi)不關(guān)閉
requestBuilder.header("Connection", "Keep-Alive");
}
// If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing
// the transfer stream.
boolean transparentGzip = false;
if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
transparentGzip = true;
// 添加 gzip 壓縮
requestBuilder.header("Accept-Encoding", "gzip");
}
List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
if (!cookies.isEmpty()) {
requestBuilder.header("Cookie", cookieHeader(cookies));
}
if (userRequest.header("User-Agent") == null) {
requestBuilder.header("User-Agent", Version.userAgent());
}
Response networkResponse = chain.proceed(requestBuilder.build());
// 將服務器返回的 Response 轉(zhuǎn)換為用戶可以用的 Response
// 接收響應頭
HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
Response.Builder responseBuilder = networkResponse.newBuilder()
.request(userRequest);
if (transparentGzip
&& "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
&& HttpHeaders.hasBody(networkResponse)) {
// 客戶端支持 Gzip 壓縮,同時服務器的響應頭是否經(jīng)過 gzip 壓縮腐泻,同時判斷響應頭是否包含 body
// 將服務器返回的數(shù)據(jù)流轉(zhuǎn)換為解壓的數(shù)據(jù)流
GzipSource responseBody = new GzipSource(networkResponse.body().source());
Headers strippedHeaders = networkResponse.headers().newBuilder()
.removeAll("Content-Encoding")
.removeAll("Content-Length")
.build();
responseBuilder.headers(strippedHeaders);
String contentType = networkResponse.header("Content-Type");
// 組織新的 Response
responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
}
return responseBuilder.build();
}
}
4.3 CacheInterceptor- 緩存攔截器
- 主要是用 InternalCache 這個類去實現(xiàn)緩存
- 不是GET方法的請求不會緩存
public final class CacheInterceptor implements Interceptor {
// 用這個類實現(xiàn)的緩存
final InternalCache cache;
public CacheInterceptor(InternalCache cache) {
this.cache = cache;
}
}
public final class Cache implements Closeable, Flushable {
@Nullable
CacheRequest put(Response response) {
String requestMethod = response.request().method();
if (HttpMethod.invalidatesCache(response.request().method())) {
try {
this.remove(response.request());
} catch (IOException var6) {
}
return null;
} else if (!requestMethod.equals("GET")) {
// 不是GET方法的請求不會緩存
return null;
} else if (HttpHeaders.hasVaryAll(response)) {
return null;
} else {
okhttp3.Cache.Entry entry = new okhttp3.Cache.Entry(response);
DiskLruCache.Editor editor = null;
try {
editor = this.cache.edit(key(response.request().url()));
if (editor == null) {
return null;
} else {
entry.writeTo(editor);
return new okhttp3.Cache.CacheRequestImpl(editor);
}
} catch (IOException var7) {
this.abortQuietly(editor);
return null;
}
}
}
}
4.4 ConnectInterceptor- 連接攔截器
打開到目標服務器的連接并繼續(xù)到下一個攔截器决乎;
- 1.Connectlnterceptor獲取Interceptor傳過來的StreamAllocation,streamAllocation.newStream();
- ⒉將剛才創(chuàng)建的用于網(wǎng)絡lO的RealConnection對象派桩,以及對于與服務器交互最為關(guān)鍵的HttpCodec等對象傳遞給后面的攔截器构诚;
public final class ConnectInterceptor implements Interceptor {
public final OkHttpClient client;
public ConnectInterceptor(OkHttpClient client) {
this.client = client;
}
@Override public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
// 從上一個攔截器獲取 StreamAllocation
StreamAllocation streamAllocation = realChain.streamAllocation();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
// 獲取 HttpCodec ,用來編碼request和解碼response
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
// 獲取 RealConnection铆惑,用來做實際的網(wǎng)絡 IO 傳輸?shù)? RealConnection connection = streamAllocation.connection();
// 調(diào)用攔截器鏈的 proceed
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
}
4.5 CallServerInterceptor- 向服務器真正發(fā)起請求攔截器
三范嘱、OkHttp 發(fā)起一次請求的大致流程
1.Call對象對請求的封裝;
2.dispatcher對請求的分發(fā)员魏;
3.getResponseWithlnterceptors()方法丑蛤;
4.RetryAndFollowUplnterceptor
5.Cachelnterceptor
6.Bridgelnterceptor
7.Connectionlnterceptor
8.CallServerlnterceptor
OkHttp自帶攔截器的執(zhí)行順序