本文源碼基於OkHttp3.14.6,該版本是Java版最新的一版,後續的4.*全面使用了Kotlin,若有須要可再進行分析。java
針對OkHttp我打算開兩篇進行分析。web
第1篇分析總體的框架設計,以及大方向的請求流程。 第2篇分析具體攔截器的功能邏輯。數組
好,咱們開始表演。緩存
在翻看源碼以前,對OkHttp的瞭解只停留在使用層面,對Api使用很是的6。徹底沒關心過內部原理。更別提設計思想了。 有句 德瑪西亞 名言咋說來着 新手拼的是英雄,技能,熟練度。高玩靠的是走位,意識,英雄池。 這句話你品,你細品~~~服務器
本文爭取以一個高玩的姿態去解讀OkHttp的源碼,至於有多高呢? 嗯~~~ 仍是這麼高。。。 websocket
咱們再看源碼的時候有一個技巧,不必定非要挨個類去逐行閱讀,枯燥無味不說,關鍵是很難和功能相對應,可根據使用方式切入,根據邏輯調用鏈,層層跟進。 本文呢又是一篇深刻淺出的題材,仍是那迷人的姿式,仍是那熟悉的套路。 從使用到原理,從架構到邏輯。 使用體現的是框架的能力,架構承載的是框架的靈魂。 咱們將從如下幾個問題出發,循循漸進,層層深刻。#####1. OkHttp有什麼優點?爲啥要分析的是OkHttp而不是其餘框架? 其實Android的網絡框架有不少,好比Android-Async-Http,Volley,OkHttp,Retrofit,那爲啥偏要分析OkHttp呢?由於它屌啊~~~ 咱們先看一個這個對比圖就明白了。markdown
對比分析 | Android-Async-Http | volley | OkHttp | Retrofit |
---|---|---|---|---|
技術分析 | 基於HttpClient | 基於HttpUrlConnection | 基於Socket, 和HttpUrlConnection同級但並不屬於HttpUrlConnection | 基於Okhttp |
優點 | 自動智能請求重試 ;持久化cookie存儲 | 1.支持圖片加載;網絡請求的排序。 2.優先級處理緩存。 3.多級別取消請求。 4.生命週期控制,退出後自動取消請求。 5.可拓展性好;可支持HttpClient、HttpUrlConnection、和OkHttp |
1.高性能Http請求庫。 2.支持SPDY,共享同一個Socket來處理同一個服務器全部的請求. 3.支持http2.0、websocket;支持同步、異步。 4.內部封裝了線程池、數據轉換、參數使用、錯誤處理等。 5.支持GZIP來減小數據流量。 6.基於NIO和OKio,性能更高。 |
1.Api牛逼 2.支持經過註解配置參數,url等信息。 3.支持Gson,Jackson,Protobuf。 4.支持RxJava。 5.代碼簡化;解耦完全。 |
劣勢 | Android5.0以後不推薦用HttpClient ,而且該框架通知維護。 | Volley的Request和Response都是把數據放到byte數組裏,不支持輸入輸出流,把數據放到數組中,若是文件多了,數組就會大,消耗內存 | ... | ... |
目前相對主流的框架Retrofit,Glide中都是內置了OkHttp,而Retrift本身便是網絡框架,且它都基於OkHttp,可見OkHttp是怎樣一個地位。cookie
#####2. OkHttp的使用方式有哪些? 接下來將秀8種操做,看好了您嘞。網絡
/** * 1.同步Get請求 * 2.異步Get請求 * 3.同步Post請求 * 4.異步Post請求 * 5.Post提交文件 * 6.Post提交from表單 * 7.文件字符串複合提交 * 8.攔截器使用 */
OkHttpClient okHttpClient = new OkHttpClient();
/** * 同步Get請求 */
private void SyncGet() {
try {
Request request = new Request.Builder()
.url("url")
.build();
Call call = okHttpClient.newCall(request);
Response response = call.execute();
} catch (Exception e) {
}
}
/** * 異步Gost請求 */
private void AsyncGet() {
Request request = new Request.Builder()
.url("url")
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//請求失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//請求成功
}
});
}
/** * 同步Post請求 */
private void SyncPost() {
try {
MediaType JSON = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
String str = "通訊數據";
Request request = new Request.Builder().url("url").post(RequestBody.create(JSON, str)).build();
Call call = okHttpClient.newCall(request);
Response response = call.execute();
} catch (Exception e) {
}
}
/** * 異步Post請求 */
private void AsyncPost() {
MediaType JSON = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
String str = "通訊數據";
Request request = new Request.Builder().url("url").post(RequestBody.create(JSON, str)).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//請求失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//請求成功
}
});
}
private void postFile() {
MediaType fileMediaType = MediaType.parse("text/x-markdown; charset=utf-8");
Request request = new Request.Builder()
.url("url")
.post(RequestBody.create(fileMediaType, new File("sd/mnt/a.png")))
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//請求失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//請求成功
}
});
}
/** * Post提交from表單 */
private void postFrom() {
MediaType fileMediaType = MediaType.parse("text/x-markdown; charset=utf-8");
Request request = new Request.Builder()
.url("url")
.post(new FormBody.Builder().add("key", "value").build())
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//請求失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//請求成功
}
});
}
/** * Post提交組合數據(字符串+文件) */
private void postMultipartBody() {
MediaType fileMediaType = MediaType.parse("image/png");
RequestBody requestBody = RequestBody.create(fileMediaType, new File("sd/mnt/1.png"));
MultipartBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "文字")//這樣能夠直接添加數據,無需單首創建RequestBody
)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(fileMediaType, new File("sd/mnt/1.png"))//這樣能夠直接添加文件,無需單首創建RequestBody
)
.addFormDataPart("key", "value")//添加表單數據
.addFormDataPart("file", "fileName", requestBody)
.build();
Request request = new Request.Builder()
.url("url")
.post(multipartBody)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//請求失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//請求成功
}
});
}
/** * 使用攔截器 */
private void postAndInterceptor() {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new MyInterceptor())
.build();
MediaType fileMediaType = MediaType.parse("image/png");
RequestBody requestBody = RequestBody.create(fileMediaType, new File("sd/mnt/1.png"));
MultipartBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("key", "value")//添加表單數據
.addFormDataPart("file", "fileName", requestBody)
.build();
Request request = new Request.Builder()
.url("url")
.post(multipartBody)
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//請求失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//請求成功
}
});
}
/** * 攔截器 */
public class MyInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
Log.d("TAG", "請求返回數據爲:" + response.body().string());
return null;
}
}
複製代碼
#####3. OkHttp的架構是什麼樣的? 這個問題挺深刻,惟有此圖以示天下。架構
上圖主要以執行流程來劃分,其主要涉及的類包含如下幾個OkHttpClient 客戶端對象
OkHttpClient.Builder 以構件者模式建立OkHttpClient對象
Request 請求對象
Response 請求結果對象。
Request.Builder 構建者模式用於建立Request
RealCall implements Call 請求控制器,用於執行request
Dispatcher 調度器,主要用於請求的策略處理。
AsyncCall是一個Runnable,線程池調用。
Callback 接收回調使用
Interceptor 攔截器接口,全部的攔截器均實現該接口,責任鏈模式的每個攔截器接口。 #####4. OkHttp的內部是咋實現的? 又到了你麼最喜歡的講道理擺姿式的環節了。 分析OkHttp的內部實現能夠從使用角度出發,以使用邏輯分析框架入口,而後層層跟進。咱們以普通的get請求爲例,主要涉及如下幾個入口。
1. OkHttpClient okHttpClient = new OkHttpClient();
2. Request request = new Request.Builder().url("url").build();
3. Call call = okHttpClient.newCall(request);
4. call.enqueue(new Callback() {... });
咱們逐個分析一下。 4.1. OkHttpClient okHttpClient = new OkHttpClient();內部執行了哪些邏輯?咱們看下源碼
//OkHttpClient的構造函數
public OkHttpClient() {
this(new Builder());
}
//OkHttpClient的構造函數
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}
if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = Util.platformTrustManager();
this.sslSocketFactory = newSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}
if (sslSocketFactory != null) {
Platform.get().configureSslSocketFactory(sslSocketFactory);
}
this.hostnameVerifier = builder.hostnameVerifier;
this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
certificateChainCleaner);
this.proxyAuthenticator = builder.proxyAuthenticator;
this.authenticator = builder.authenticator;
this.connectionPool = builder.connectionPool;
this.dns = builder.dns;
this.followSslRedirects = builder.followSslRedirects;
this.followRedirects = builder.followRedirects;
this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
this.callTimeout = builder.callTimeout;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.writeTimeout = builder.writeTimeout;
this.pingInterval = builder.pingInterval;
if (interceptors.contains(null)) {
throw new IllegalStateException("Null interceptor: " + interceptors);
}
if (networkInterceptors.contains(null)) {
throw new IllegalStateException("Null network interceptor: " + networkInterceptors);
}
}
//OkHttpClient 中靜態內部類Builder的構造方法
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
proxySelector = new NullProxySelector();
}
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
callTimeout = 0;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
//OkHttpClient 中靜態內部類Builder的構造方法
Builder(OkHttpClient okHttpClient) {
this.dispatcher = okHttpClient.dispatcher;
this.proxy = okHttpClient.proxy;
this.protocols = okHttpClient.protocols;
this.connectionSpecs = okHttpClient.connectionSpecs;
this.interceptors.addAll(okHttpClient.interceptors);
this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
this.eventListenerFactory = okHttpClient.eventListenerFactory;
this.proxySelector = okHttpClient.proxySelector;
this.cookieJar = okHttpClient.cookieJar;
this.internalCache = okHttpClient.internalCache;
this.cache = okHttpClient.cache;
this.socketFactory = okHttpClient.socketFactory;
this.sslSocketFactory = okHttpClient.sslSocketFactory;
this.certificateChainCleaner = okHttpClient.certificateChainCleaner;
this.hostnameVerifier = okHttpClient.hostnameVerifier;
this.certificatePinner = okHttpClient.certificatePinner;
this.proxyAuthenticator = okHttpClient.proxyAuthenticator;
this.authenticator = okHttpClient.authenticator;
this.connectionPool = okHttpClient.connectionPool;
this.dns = okHttpClient.dns;
this.followSslRedirects = okHttpClient.followSslRedirects;
this.followRedirects = okHttpClient.followRedirects;
this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
this.callTimeout = okHttpClient.callTimeout;
this.connectTimeout = okHttpClient.connectTimeout;
this.readTimeout = okHttpClient.readTimeout;
this.writeTimeout = okHttpClient.writeTimeout;
this.pingInterval = okHttpClient.pingInterval;
}
//經過靜態內部類Builder的build()方法可建立 OkHttpClient 對象。
public OkHttpClient build() {
return new OkHttpClient(this);
}
複製代碼
咱們分析下這一大段代碼,其實邏輯內容很是簡單,主要乾了這麼幾件事。
4.2. Request request = new Request.Builder().url("url").build();內部又幹了啥? 從寫法上看,Request 同樣也使用了構建者模式,咱們分開Request.Builder(),url("url"),build()一個一個看。
//Request構造函數
Request(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers.build();
this.body = builder.body;
this.tags = Util.immutableMap(builder.tags);
}
//Request的靜態內部類Builder構造函數
public Builder() {
this.method = "GET";
this.headers = new Headers.Builder();
}
//Request的靜態內部類Builder構造函數
Builder(Request request) {
this.url = request.url;
this.method = request.method;
this.body = request.body;
this.tags = request.tags.isEmpty()
? Collections.emptyMap()
: new LinkedHashMap<>(request.tags);
this.headers = request.headers.newBuilder();
}
//Request的靜態內部類Builder設置url方法
public Builder url(HttpUrl url) {
if (url == null) throw new NullPointerException("url == null");
this.url = url;
return this;
}
/** * Request的靜態內部類Builder設置url方法 * * @若是url是無效的則拋出 throws IllegalArgumentException 經過調用HttpUrl.get(url)避免這種異常, * 無效的url返回null */
public Builder url(String url) {
if (url == null) throw new NullPointerException("url == null");
// Silently replace web socket URLs with HTTP URLs.
if (url.regionMatches(true, 0, "ws:", 0, 3)) {
url = "http:" + url.substring(3);
} else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
url = "https:" + url.substring(4);
}
return url(HttpUrl.get(url));
}
/** * Request的靜態內部類Builder設置url方法 * * @throws IllegalArgumentException if the scheme of {@code url} is not {@code http} or {@code * https}. */
public Builder url(URL url) {
if (url == null) throw new NullPointerException("url == null");
return url(HttpUrl.get(url.toString()));
}
// Request的靜態內部類Builder設置build方法
public Request build() {
if (url == null) throw new IllegalStateException("url == null");
return new Request(this);
}
複製代碼
咱們總結下 new Request.Builder().url("url").build()幹了幾件事。
4.3. Call call = okHttpClient.newCall(request);又是幹什麼的呢? 以上的4.1 , 4.2均是爲了建立okHttpClient,Request對象,以及初始化一數據,並無進行其餘操做。 okHttpClient.newCall(request);又作了什麼操做呢?
/** * okHttpClient的newCall() * 準備request,將在某個時間執行。 */
@Override public Call newCall(Request request) {
//最後這個參數是否爲web socket默認傳false
return RealCall.newRealCall(this, request, false /* for web socket */);
}
/** *RealCall.newRealCall(...) *實例化RealCall對象,初始化RealCall.transmitter。 */
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.transmitter = new Transmitter(client, call);
return call;
}
/** *RealCall(...) */
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
}
/** *Transmitter類構造函數 。 */
public Transmitter(OkHttpClient client, Call call) {
this.client = client;
this.connectionPool = Internal.instance.realConnectionPool(client.connectionPool());
this.call = call;
this.eventListener = client.eventListenerFactory().create(call);
this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
}
複製代碼
總結:這一堆竟然仍是在建立對象,真正的請求尚未開始。
4.4. call.enqueue(new Callback() {... });應該開始請求了吧... 前邊準備的全部準備均爲了最後這一步請求,咱們看下邏輯是怎麼操做的。
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
transmitter.callStart();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
//transmitter.callStart();
public void callStart() {
this.callStackTrace = Platform.get().getStackTraceForCloseable("response.body().close()");
eventListener.callStart(call);
}
複製代碼
這塊有點複雜咱們一點一點的分析,最後進行總結。 首先call.enqueue()中進行了執行狀態賦值,防止重複執行請求。 其次調用了transmitter.callStart();啓動堆棧的跟蹤,以及eventListener的一些回調處理。 最後便是最關鍵的異步 client.dispatcher().enqueue(new AsyncCall(responseCallback));是真正的請求流程。 我繼續深刻分析
//Dispatcher.enqueue()
void enqueue(AsyncCall call) {
synchronized (this) {
//readyAsyncCalls是一個準備調用的AsyncCall隊列
readyAsyncCalls.add(call);
// 若是不是WebSocket,將經過call.host查找是否有運行中的AsyncCall ,若是有將經過AtomicInteger類型共享到當前 AsyncCall 對象中。
if (!call.get().forWebSocket) {
AsyncCall existingCall = findExistingCallWithHost(call.host());
//異步請求,OkHttp會對有相同主機的call在請求時進行記數,經過AtomicInteger對象進行即時同步。
//這個計數對後續的請求有影響,咱們後邊再詳細分析。
if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
}
}
//真正執行操做
promoteAndExecute();
}
//循環runningAsyncCalls和readyAsyncCalls隊列
@Nullable private AsyncCall findExistingCallWithHost(String host) {
for (AsyncCall existingCall : runningAsyncCalls) {
if (existingCall.host().equals(host)) return existingCall;
}
for (AsyncCall existingCall : readyAsyncCalls) {
if (existingCall.host().equals(host)) return existingCall;
}
return null;
}
/** *readyAsyncCalls中知足條件的對象移動到runningAsyncCalls中 而且在 executor service上運行。 * 必須同步調用,由於要回調用戶的代碼 * * 若是調度程序當前正在運行,則返回true */
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
//循環readyAsyncCalls隊列。
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
//若是運行隊列runningAsyncCalls超過了maxRequests直接break。(默認值爲64)
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
//若是當前的主機計數器>5則continue,這個計數器就是上述enqueue()方法的計數器。
if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
從readyAsyncCalls中移除
i.remove();
//相同主機的asyncCall計數器+1
asyncCall.callsPerHost().incrementAndGet();
executableCalls.add(asyncCall);
//添加到runningAsyncCalls隊列中
runningAsyncCalls.add(asyncCall);
}
//運行狀態賦值,異步/同步只要有一個在運行則爲true。
isRunning = runningCallsCount() > 0;
}
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
//開始運行,具體的運行邏輯咱們後續分析。
asyncCall.executeOn(executorService());
}
return isRunning;
}
複製代碼
ok,咱們總結下Dispatcher.enqueue()幹了什麼事
那**asyncCall.executeOn(executorService());**中又幹了啥?
//Dispatcher.executorService()
//若是executorService 爲null則建立一個ThreadPoolExecutor線程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
/** * AsyncCall.executeOn() * 嘗試經過 executorService啓動執行AsyncCall * 若是 executor已經關閉了則嘗試清楚,並報失敗 */
void executeOn(ExecutorService executorService) {
assert (!Thread.holdsLock(client.dispatcher()));
boolean success = false;
try {
//線程池執行AsyncCall
executorService.execute(this);
success = true;
} catch (RejectedExecutionException e) {
InterruptedIOException ioException = new InterruptedIOException("executor rejected");
ioException.initCause(e);
transmitter.noMoreExchanges(ioException);
//回調onFailure
responseCallback.onFailure(RealCall.this, ioException);
} finally {
if (!success) {
//若是沒成功,調用OkHttpClient.dispatcher().finished(this);
client.dispatcher().finished(this); // This call is no longer running!
}
}
}
/** * Dispatcher.finished() *失敗 */
void finished(AsyncCall call) {
//AsyncCall 中相同主機計數器-1。
call.callsPerHost().decrementAndGet();
finished(runningAsyncCalls, call);
}
//Dispatcher.finished(...)
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
//從runningAsyncCalls中移除call。
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
//從新調用promoteAndExecute()
boolean isRunning = promoteAndExecute();
if (!isRunning && idleCallback != null) {
//若是同步異步均沒有運行了而且idleCallback 不爲空 則通知當前爲空閒狀態了。
idleCallback.run();
}
}
複製代碼
咱們再總結下asyncCall.executeOn(executorService())到底幹了啥。
executorService.execute(this);是執行請求的邏輯內容,咱們詳細看下 executorService是一個線程池,而this表明的是AsyncCall這個類,如今其實能夠發現AsyncCall實際上繼承的是NamedRunnable,而NamedRunnable實現了Runnable,這下就簡單了,咱們直接找Runnable的run方法便可。
public abstract class NamedRunnable implements Runnable {
...
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
//主要執行了這個方法,這個方法實際是一個抽象方法,須要看實現類的實現。
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
//AsyncCall.execute()
@Override
protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
Response response = getResponseWithInterceptorChain();
signalledCallback = true;
//回調結果
responseCallback.onResponse(RealCall.this, response);
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
responseCallback.onFailure(RealCall.this, e);
}
} catch (Throwable t) {
cancel();
if (!signalledCallback) {
IOException canceledException = new IOException("canceled due to " + t);
canceledException.addSuppressed(t);
responseCallback.onFailure(RealCall.this, canceledException);
}
throw t;
} finally {
//移除當前AsyncCall
client.dispatcher().finished(this);
}
}
複製代碼
咱們觀察以上代碼大部分是異常處理的邏輯,而try中第一句即返回了Response對象,所以,咱們主要看getResponseWithInterceptorChain()中的邏輯。
Response getResponseWithInterceptorChain() throws IOException {
// 創建一個完整的攔截器堆棧
List<Interceptor> interceptors = new ArrayList<>();
//將建立okhttpclient時的攔截器添加到interceptors
interceptors.addAll(client.interceptors());
//重試攔截器,負責處理失敗後的重試與重定向
interceptors.add(new RetryAndFollowUpInterceptor(client));
//請求轉化攔截器(用戶請求轉爲服務器請求,服務器響應轉爲用戶響應)
interceptors.add(new BridgeInterceptor(client.cookieJar()));
//緩存攔截器。負責
//1.根據條件,緩存配置,有效期等返回緩存響應,也可增長到緩存。
//2.設置請求頭(If-None-Match、If-Modified-Since等) 服務器可能返回304(未修改)
//3.可配置自定義的緩存攔截器。
interceptors.add(new CacheInterceptor(client.internalCache()));
//網絡鏈接攔截器,主要負責和服務器創建鏈接。
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
//建立okhttpclient時設置的networkInterceptors
interceptors.addAll(client.networkInterceptors());
}
//數據流攔截器,主要負責像服務器發送和讀取數據,請求報文封裝和解析。
interceptors.add(new CallServerInterceptor(forWebSocket));
//責任鏈模式的建立。
Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
try {
//啓動責任鏈
Response response = chain.proceed(originalRequest);
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}
複製代碼
其實上述邏輯中,主要乾了3件事。
咱們只要搞懂建立責任鏈的邏輯,以及啓動責任鏈的邏輯就全都明白了,ok,咱們看下具體代碼
//經過RealInterceptorChain構造函數建立每個責任對象
public RealInterceptorChain(List<Interceptor> interceptors, Transmitter transmitter, @Nullable Exchange exchange, int index, Request request, Call call, int connectTimeout, int readTimeout, int writeTimeout) {
this.interceptors = interceptors;
this.transmitter = transmitter;
this.exchange = exchange;
this.index = index;
this.request = request;
this.call = call;
this.connectTimeout = connectTimeout;
this.readTimeout = readTimeout;
this.writeTimeout = writeTimeout;
}
//啓動責任鏈代碼
@Override
public Response proceed(Request request) throws IOException {
return proceed(request, transmitter, exchange);
}
//啓動責任鏈代碼
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// 若是咱們已經有一個流,請確認傳入的請求將使用它。
if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// 若是咱們已經有一個流,確認這是對鏈的惟一調用。
if (this.exchange != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// 調用鏈中的下一個攔截器,注意參數index+1,經過+1的方式循環interceptors list中的攔截器
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
Interceptor interceptor = interceptors.get(index);
//執行當前攔截器邏輯,並設置下一個攔截器對象。
Response response = interceptor.intercept(next);
// 確認下一個攔截器對chain.proceed()進行了所需的調用。
if (exchange != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
複製代碼
雖然看着上述這段代碼很長,可是大篇幅都在判斷各類異常狀況,實際作的事很是簡單。 1.建立完RealInterceptorChain後,經過procee()判斷各類異常,並獲取當前Interceptor對象。 2.經過Interceptor.intercept(RealInterceptorChain)啓動當前攔截器邏輯,而且觸發下一個攔截器啓動。 3.若是當前攔截器出現異常等錯誤,則終止責任鏈。
具體的狀況咱們還須要看一個攔截器內部的邏輯,咱們以簡單的ConnectInterceptor爲例。
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 {
//chain其實是下一個責任對象。
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
Transmitter transmitter = realChain.transmitter();
// 咱們須要網絡來知足這個要求。可能用於驗證條件GET。
boolean doExtensiveHealthChecks = !request.method().equals("GET");
Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);
//執行下一個攔截器責任對象的proceed方法。
return realChain.proceed(request, transmitter, exchange);
}
}
複製代碼
可見,Interceptor.intercept(Chain chain)接收的是下一個攔截器責任對象。 該方法中執行了本身攔截器該有的邏輯,若是沒異常則直接經過下一個攔截器責任對象的proceed()啓動了下一個攔截器邏輯。 ok咱們在回頭看下,AsyncCall.execute()中的finally中的那句代碼 client.dispatcher().finished(this);
//Dispatcher.finished()
void finished(AsyncCall call) {
call.callsPerHost().decrementAndGet();
finished(runningAsyncCalls, call);
}
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
//移除隊列,若是失敗則拋異常
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
//這個方法是否是有點眼熟,主要用來將readyAsyncCalls符合條件的添加到runningAsyncCalls中,並運行。
boolean isRunning = promoteAndExecute();
//閒置調用
if (!isRunning && idleCallback != null) {
idleCallback.run();
}
}
複製代碼
ok至此全部的流程都很是清楚了。至於請求細節須要具體到了每個攔截器裏。我打算單獨開一篇來分析。 看到此處,若是對你有一點幫助,麻煩給個贊鼓勵一下。
其實寫博客是一個自驅的學習管理方式。能給小夥伴說明白的,那你一定早已心中有數。翻閱偉大的框架代碼就比如面對面跟這個偉人學習。