1. okHttp的使用
- 1.1 構(gòu)造并配置okHttpClient
OkHttpClient okHttpClient = new OkHttpClient();
然后看下配置項(xiàng):
final Dispatcher dispatcher;//調(diào)度器,線程管理
final @Nullable Proxy proxy;//代理
final List<Protocol> protocols;//協(xié)議(如Http1.1夺英,Http2)
final List<ConnectionSpec> connectionSpecs;//傳輸層版本和連接協(xié)議
final List<Interceptor> interceptors;//攔截器
final List<Interceptor> networkInterceptors;//網(wǎng)絡(luò)攔截器
final EventListener.Factory eventListenerFactory;
final ProxySelector proxySelector;//代理選擇器
final CookieJar cookieJar;//cookie
final @Nullable Cache cache;//緩存
final @Nullable InternalCache internalCache;//內(nèi)部緩存
final SocketFactory socketFactory;//socket工廠
final @Nullable SSLSocketFactory sslSocketFactory;//安全套層socket工廠撩独,用于https
final @Nullable CertificateChainCleaner certificateChainCleaner;//驗(yàn)證確認(rèn)響應(yīng)證書
final HostnameVerifier hostnameVerifier;//主機(jī)名確認(rèn)
final CertificatePinner certificatePinner;//用于自簽名證書
final Authenticator proxyAuthenticator;//代理身份驗(yàn)證
final Authenticator authenticator;//本地身份驗(yàn)證
final ConnectionPool connectionPool;/連接池
final Dns dns;//dns
final boolean followSslRedirects;/安全套接層重定向
final boolean followRedirects;//本地重定向(http和https互相跳轉(zhuǎn)時(shí)媒抠,默認(rèn)為true)
final boolean retryOnConnectionFailure;//連接失敗重試
final int connectTimeout;//連接超時(shí)時(shí)間
final int readTimeout;//讀取超時(shí)時(shí)間
final int writeTimeout;//寫入超時(shí)時(shí)間
final int pingInterval;//ping的間隔
其實(shí)構(gòu)建OkHttpClient時(shí)okHttp已經(jīng)幫我們實(shí)現(xiàn)了默認(rèn)配置牧愁,我們可以根據(jù)需要進(jìn)行修改毅否。
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
okHttpBuilder.addInterceptor(...);
okHttpBuilder.cache(...);
OkHttpClient okHttpClient = okHttpBuilder.build();
-
1.2 構(gòu)造并配置Request
Request.Builder builder = new Request.Builder(); builder.url("http://v.juhe.cn/"); Request request = builder.build();
這里只配置了url,再看下其他的配置項(xiàng):
public Builder() { this.method = "GET"; this.headers = new Headers.Builder(); } Builder(Request request) { this.url = request.url; this.method = request.method; this.body = request.body; this.tag = request.tag; this.headers = request.headers.newBuilder(); }
可以看到如果不設(shè)置的話玄渗,默認(rèn)是GET請(qǐng)求碉咆,同時(shí)還可以設(shè)置body,tag,headers等信息骏庸。
-
1.3 構(gòu)造Call并執(zhí)行網(wǎng)絡(luò)請(qǐng)求
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 { } });
以上就是okHttp等基本使用(一般結(jié)合Retrofit,效果更佳)敌土。
2. okHttp的調(diào)用流程源碼分析
-
2.1 從使用中可以看到首先通過newCall()方法構(gòu)造了一個(gè)Call,那么看下newCall():
@Override public Call newCall(Request request) { return new RealCall(this, request, false); }
newCall()實(shí)際返回了一個(gè)RealCall,那么執(zhí)行的enqueue()就是RealCall的enqueue():
@Override public void enqueue(Callback responseCallback) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); client.dispatcher().enqueue(new AsyncCall(responseCallback)); }
可以看到在RealCall的enqueue()中實(shí)際執(zhí)行了dispatcher的enqueue(AsyncCall(responseCallback))压彭,并傳入了AsyncCall,dispatcher其實(shí)是一個(gè)調(diào)度器菌羽,用來調(diào)度請(qǐng)求網(wǎng)絡(luò)的線程掠械。看一下它的enqueue():
synchronized void enqueue(AsyncCall call) { if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { runningAsyncCalls.add(call); executorService().execute(call); } else { readyAsyncCalls.add(call); } }
從上面代碼可以看到注祖,先判斷正在執(zhí)行的任務(wù)是否超過最大請(qǐng)求數(shù)猾蒂,如果超了就先存進(jìn)去。是晨,如果沒超則使用ExecutorService直接執(zhí)行肚菠,再看執(zhí)行的這個(gè)call,它是一個(gè)AsyncCall,AsyncCall繼承了NamedRunnable,NamedRunnable則繼承了Runnable罩缴,所以AsyncCall是一個(gè)Runnable蚊逢,同時(shí)NamedRunnable的run()執(zhí)行了execute(),AsyncCall重寫了execute()箫章,所以最后會(huì)執(zhí)行到AsyncCall的execute()里:
@Override protected void execute() { boolean signalledCallback = false; try { Response response = getResponseWithInterceptorChain(); if (retryAndFollowUpInterceptor.isCanceled()) { signalledCallback = true; responseCallback.onFailure(RealCall.this, new IOException("Canceled")); } else { 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); } } finally { client.dispatcher().finished(this); } } }
可以看到getResponseWithInterceptorChain()返回了請(qǐng)求結(jié)果烙荷,然后就通過回調(diào)返回給調(diào)用端了,這個(gè)就是大概的調(diào)用流程炉抒。
那么這個(gè)getResponseWithInterceptorChain()其實(shí)就完成了請(qǐng)求前的數(shù)據(jù)處理奢讨,建立連接,對(duì)返回?cái)?shù)據(jù)進(jìn)行處理等操作焰薄。那么這個(gè)getResponseWithInterceptorChain()其實(shí)就是整個(gè)okHttp的重點(diǎn)拿诸。
-
2.2 看一下getResponseWithInterceptorChain()代碼:
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 (!forWebSocket) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor(forWebSocket)); Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest); }
可以看到這個(gè)方法里添加了一系列的Interceptor,然后把Interceptor集合傳遞給RealInterceptorChain塞茅,構(gòu)建了一個(gè)Chain亩码。最后執(zhí)行了chain.proceed(),這里使用了責(zé)任鏈模式野瘦,它的執(zhí)行流程大概是這樣的:
Interceptor最重要的就是它的intercept()方法描沟,所有核心邏輯都在這里。
先執(zhí)行第一個(gè)Interceptor的前置邏輯鞭光,然后執(zhí)行chain.proceed()吏廉,把任務(wù)轉(zhuǎn)交給下一個(gè)Interceptor,下一個(gè)Interceptor同樣執(zhí)行它的前置邏輯惰许,完成后通過chain.proceed()把任務(wù)繼續(xù)傳遞下去席覆,直到最后一個(gè)Interceptor。最后一個(gè)Interceptor獲取到結(jié)果后返回到上一個(gè)Interceptor汹买,執(zhí)行它的后置邏輯佩伤,執(zhí)行完后再返回給上一次聊倔,最后返回結(jié)果給getResponseWithInterceptorChain()。
總結(jié)一下:當(dāng)我們發(fā)起一個(gè)請(qǐng)求后生巡,當(dāng)來到getResponseWithInterceptorChain()時(shí)耙蔑,它添加了一系列Interceptor,構(gòu)成一個(gè)責(zé)任鏈孤荣。每一層的Interceptor通過前置邏輯對(duì)請(qǐng)求的原始數(shù)據(jù)(request)進(jìn)行加工甸陌,然后再通過chain.proceed()把任務(wù)傳遞給下一層,當(dāng)傳遞到最后一個(gè)Interceptor時(shí)會(huì)返回請(qǐng)求的結(jié)果(response)垃环,然后再逐層返回邀层,通過每一層的后置邏輯對(duì)結(jié)果(response)進(jìn)行處理,最后返回給請(qǐng)求端遂庄。
所以我們可以通過添加自定義Interceptor的方式寥院,在請(qǐng)求前通過前置邏輯對(duì)請(qǐng)求request進(jìn)行修改,如添加header等涛目。等返回結(jié)果后秸谢,通過后置邏輯對(duì)返回?cái)?shù)據(jù)response進(jìn)行處理。OkHttp通過OkHttpClient.Builder的addInterceptor()和addNetworkInterceptor()支持了添加自定義Interceptor霹肝,后面會(huì)說到估蹄。
-
2.3 那么再看一下每個(gè)Interceptor具體都做了什么
-
2.3.1 添加自定義的Interceptor
interceptors.addAll(client.interceptors());
可以看到,第一步其實(shí)是添加了我們自定義的所有的Interceptor沫换,一般來說可以添加一些信息如:
builder.addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { //前置邏輯 Request request = chain.request().newBuilder() .addHeader("Content-Type", ...) .addHeader("Date", ...) .addHeader("User-Agent", ...) .addHeader("uid",...) .build(); //傳遞任務(wù)給下一層 Response response = chain.proceed(request); //后置邏輯臭蚁,這里已經(jīng)拿到了請(qǐng)求結(jié)果,可以根據(jù)需要對(duì)結(jié)果直接進(jìn)行處理 return response; } });
-
2.3.2 添加RetryAndFollowUpInterceptor
interceptors.add(retryAndFollowUpInterceptor);
從名字可以看出這是一個(gè)重試的Interceptor,再看它的intercept():
//篇幅原因讯赏,省略了很多代碼 @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); //前置邏輯垮兑,初始化連接對(duì)象 streamAllocation = new StreamAllocation( client.connectionPool(), createAddress(request.url()), callStackTrace); while (true) { //是否已取消了連接 if (canceled) { streamAllocation.release(); throw new IOException("Canceled"); } try { //移交任務(wù),等待結(jié)果 response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null); releaseConnection = false; } catch (RouteException e) { //路由出錯(cuò)漱挎,判斷是否進(jìn)行重試 if (!recover(e.getLastConnectException(), false, request)) { throw e.getLastConnectException(); } } Request followUp = followUpRequest(response); //如果followUp返回空系枪,則代表請(qǐng)求成功,直接結(jié)束循環(huán)磕谅,如果請(qǐng)求失敗私爷,那么生成新的request在條件符合的時(shí)候去重試 if (followUp == null) { if (!forWebSocket) { streamAllocation.release(); } return response; } }
請(qǐng)注意,這里省略了很多代碼膊夹,判斷條件不是全部衬浑。之后的Interceptor同樣會(huì)省略,不再提示
首先RetryAndFollowUpInterceptor的前置邏輯是初始化了一個(gè)連接對(duì)象StreamAllocation放刨,然后判斷是否取消了請(qǐng)求嚎卫,請(qǐng)求過程中是否路由出錯(cuò),取消或出錯(cuò)的話就直接拋出異常,否則執(zhí)行proceed()傳遞請(qǐng)求拓诸,然后等待請(qǐng)求結(jié)果。請(qǐng)求結(jié)果返回后麻昼,執(zhí)行后置邏輯奠支,根據(jù)設(shè)置的條件對(duì)結(jié)果進(jìn)行判斷,看是否需要去重試抚芦,如果需要?jiǎng)t再次進(jìn)入while()循環(huán)進(jìn)行請(qǐng)求倍谜,是否需要進(jìn)行重定向,都不需要?jiǎng)t直接返回結(jié)果叉抡。(注意尔崔!這里省略了一些代碼)
-
2.3.3 添加BridgeInterceptor
interceptors.add(new BridgeInterceptor(client.cookieJar()));
可以看到,這一步添加了BridgeInterceptor褥民,并且傳入了CookieJar季春,那么意味著,可以自定義自己的cookieJar:
OkHttpClient okHttpClient = okHttpBuilder .cookieJar(new CookieJar() { @Override public void saveFromResponse(HttpUrl url, List<Cookie> cookies) { //保存cookie } @Override public List<Cookie> loadForRequest(HttpUrl url) { //加載cookie return null; } }) .build();
再看它的intercept():
@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) { 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()); 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)) { GzipSource responseBody = new GzipSource(networkResponse.body().source()); Headers strippedHeaders = networkResponse.headers().newBuilder() .removeAll("Content-Encoding") .removeAll("Content-Length") .build(); responseBuilder.headers(strippedHeaders); responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody))); } return responseBuilder.build(); }
首先BridgeInterceptor的前置邏輯對(duì)請(qǐng)求的header進(jìn)行了設(shè)置消返,調(diào)用者設(shè)置過的就直接使用载弄,沒設(shè)置過的則設(shè)置一個(gè)默認(rèn)的。然后還添加了gzip壓縮的支持撵颊。然后執(zhí)行proceed()傳遞請(qǐng)求宇攻,等待請(qǐng)求結(jié)果。請(qǐng)求結(jié)果返回后倡勇,執(zhí)行后置邏輯逞刷,這里的后置邏輯主要就是對(duì)數(shù)據(jù)進(jìn)行了解壓縮后返回。
-
2.3.4 添加CacheInterceptor
interceptors.add(new CacheInterceptor(client.internalCache()));
從名字可以看出它是一個(gè)緩存的Interceptor妻熊,并且傳入了Cache,那么意味著可以自定義Cache:
File cacheFile = new File(...); Cache cache = new Cache(cacheFile, ...); OkHttpClient okHttpClient = okHttpBuilder .cache(cache) .build();
再看它的intercept():
//篇幅原因夸浅,省略了很多代碼 @Override public Response intercept(Chain chain) throws IOException { //創(chuàng)建緩存策略 CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get(); // If we're forbidden from using the network and the cache is insufficient, fail. //如果網(wǎng)絡(luò)有問題,同時(shí)沒有緩存固耘,就構(gòu)建并返回一個(gè)code是504的response if (networkRequest == null && cacheResponse == null) { return new Response.Builder() .request(chain.request()) .protocol(Protocol.HTTP_1_1) .code(504) .message("Unsatisfiable Request (only-if-cached)") .body(Util.EMPTY_RESPONSE) .sentRequestAtMillis(-1L) .receivedResponseAtMillis(System.currentTimeMillis()) .build(); } // If we don't need the network, we're done. //如果網(wǎng)絡(luò)有問題题篷,則使用緩存構(gòu)建并返回一個(gè)response if (networkRequest == null) { return cacheResponse.newBuilder() .cacheResponse(stripBody(cacheResponse)) .build(); } Response networkResponse =networkResponse = chain.proceed(networkRequest); if (cacheResponse != null) { //服務(wù)器返回304,代表內(nèi)容沒有更新厅目,繼續(xù)使用緩存 if (networkResponse.code() == HTTP_NOT_MODIFIED) { Response response = cacheResponse.newBuilder() .headers(combine(cacheResponse.headers(), networkResponse.headers())) .sentRequestAtMillis(networkResponse.sentRequestAtMillis()) .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis()) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); networkResponse.body().close(); return response; } else { closeQuietly(cacheResponse.body()); } } //讀取網(wǎng)路結(jié)果 Response response = networkResponse.newBuilder() .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); //進(jìn)行緩存 if (cache != null) { CacheRequest cacheRequest = cache.put(response); return cacheWritingResponse(cacheRequest, response); } } //返回結(jié)果 return response; }
首先CacheInterceptor的前置邏輯創(chuàng)建了一個(gè)緩存策略番枚,然后判斷網(wǎng)絡(luò)是否有問題,有問題的話是否有緩存损敷,有緩存直接返回緩存葫笼,沒有緩存的話則則直接返回一個(gè)帶錯(cuò)誤信息的Response,不再往下執(zhí)行。如果有網(wǎng)絡(luò)也沒緩存拗馒,那么執(zhí)行proceed()傳遞請(qǐng)求路星,等待結(jié)果。返回結(jié)果后,在后置邏輯中洋丐,如果結(jié)果返回304則代表服務(wù)器沒有更新數(shù)據(jù)呈昔,直接返回緩存。如果正常返回?cái)?shù)據(jù)則讀取結(jié)果后對(duì)結(jié)果進(jìn)行緩存后返回友绝。
-
2.3.5 添加ConnectInterceptor
interceptors.add(new ConnectInterceptor(client));
從名字可以看出這是一個(gè)連接的Interceptor堤尾,再看它的intercept():
@Override public Response intercept(Chain chain) throws IOException { RealInterceptorChain realChain = (RealInterceptorChain) chain; Request request = realChain.request(); //獲取連接對(duì)象 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 httpCodec = streamAllocation.newStream(client, doExtensiveHealthChecks); //獲取連接 RealConnection connection = streamAllocation.connection(); return realChain.proceed(request, streamAllocation, httpCodec, connection); }
ConnectInterceptor的intercept()中首先獲取了之前構(gòu)建的連接對(duì)象StreamAllocation迁客,然后建立了連接郭宝,生成了編碼解碼器,獲取了連接后執(zhí)行 realChain.proceed(request, streamAllocation, httpCodec, connection)掷漱,傳遞請(qǐng)求給下一層粘室,同時(shí)直接返回結(jié)果,沒有后置邏輯卜范。
-
2.3.6 添加networkInterceptors
interceptors.addAll(client.networkInterceptors());
可以看到衔统,這個(gè)networkInterceptors位置是在建立連接之后,寫數(shù)據(jù)以及獲取數(shù)據(jù)之前先朦,所以它一般是對(duì)發(fā)出的請(qǐng)求做最后的處理以及拿到數(shù)據(jù)后最初的處理缰冤,如使用Stetho抓包時(shí)可以添加:
builder.addNetworkInterceptor(new StethoInterceptor());
-
2.3.7 添加CallServerInterceptor
interceptors.add(new CallServerInterceptor(forWebSocket));
看一下它的intercept():
@Override public Response intercept(Chain chain) throws IOException { RealInterceptorChain realChain = (RealInterceptorChain) chain; HttpCodec httpCodec = realChain.httpStream(); StreamAllocation streamAllocation = realChain.streamAllocation(); RealConnection connection = (RealConnection) realChain.connection(); Request request = realChain.request(); long sentRequestMillis = System.currentTimeMillis(); //寫頭信息 httpCodec.writeRequestHeaders(request); Response.Builder responseBuilder = null; if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) { // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100 // Continue" response before transmitting the request body. If we don't get that, return what // we did get (such as a 4xx response) without ever transmitting the request body. if ("100-continue".equalsIgnoreCase(request.header("Expect"))) { httpCodec.flushRequest(); responseBuilder = httpCodec.readResponseHeaders(true); } if (responseBuilder == null) { // Write the request body if the "Expect: 100-continue" expectation was met. Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength()); BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut); request.body().writeTo(bufferedRequestBody); bufferedRequestBody.close(); } else if (!connection.isMultiplexed()) { // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection from // being reused. Otherwise we're still obligated to transmit the request body to leave the // connection in a consistent state. streamAllocation.noNewStreams(); } } httpCodec.finishRequest(); if (responseBuilder == null) { responseBuilder = httpCodec.readResponseHeaders(false); } //構(gòu)建response Response response = responseBuilder .request(request) .handshake(streamAllocation.connection().handshake()) .sentRequestAtMillis(sentRequestMillis) .receivedResponseAtMillis(System.currentTimeMillis()) .build(); int code = response.code(); if (forWebSocket && code == 101) { // Connection is upgrading, but we need to ensure interceptors see a non-null response body. response = response.newBuilder() .body(Util.EMPTY_RESPONSE) .build(); } else { //獲取body信息 response = response.newBuilder() .body(httpCodec.openResponseBody(response)) .build(); } if ("close".equalsIgnoreCase(response.request().header("Connection")) || "close".equalsIgnoreCase(response.header("Connection"))) { streamAllocation.noNewStreams(); } if ((code == 204 || code == 205) && response.body().contentLength() > 0) { throw new ProtocolException( "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength()); } return response; }
這個(gè)Interceptor是最后一個(gè),連接之前的ConnectInterceptor已經(jīng)建立喳魏,這里就只需要寫數(shù)據(jù)和讀數(shù)據(jù)就行了棉浸,可以看到writeRequestHeaders()先寫了頭信息,之后再寫body等刺彩。然后等數(shù)據(jù)返回后讀取迷郑,然后返回給上一層。由于它是最后一個(gè)Interceptor所以它不需要再傳遞請(qǐng)求创倔,直接返回就OK了嗡害。
-
3. okHttp調(diào)用流程總結(jié)
構(gòu)建okHttpClient,并添加需要的配置畦攘。如添加自定義的Interceptor霸妹,是否重連,設(shè)置超時(shí)時(shí)間知押,Cookie叹螟,Cache等。
配置Request台盯,如請(qǐng)求方法罢绽,請(qǐng)求頭,請(qǐng)求體等静盅。
通過okHttpClient.newCall(request)生成Call對(duì)象良价,這個(gè)Call實(shí)際是RealCall。
-
執(zhí)行它的enqueue(),最后實(shí)際會(huì)執(zhí)行到AsyncCall的execute()中,然后執(zhí)行它的getResponseWithInterceptorChain()等待返回結(jié)果明垢。
在getResponseWithInterceptorChain()中使用了責(zé)任鏈模式蚣常,每一個(gè)節(jié)點(diǎn)是一個(gè)interceptor,在哦它的interceptors()中:添加前置邏輯袖外,然后調(diào)用proceed方法史隆,傳遞請(qǐng)求到下一層,等待結(jié)果返回曼验,直達(dá)最后網(wǎng)絡(luò)請(qǐng)求完成返回?cái)?shù)據(jù),又原路返回執(zhí)行每一個(gè)interceptors的后置邏輯粘姜。
getResponseWithInterceptorChain()首先執(zhí)行了自定義的Interceptor的前置邏輯鬓照,它獲取了用戶設(shè)置的自定義配置并添加到請(qǐng)求中,然后轉(zhuǎn)交給下一層孤紧,并等待結(jié)果返回豺裆。
第二個(gè)執(zhí)行了RetryAndFollowUpInterceptor的前置邏輯,它初始化了連接對(duì)象号显,如果沒有取消請(qǐng)求臭猜,則繼續(xù)轉(zhuǎn)交請(qǐng)求給下一層,并等待結(jié)果返回押蚤。
第三個(gè)執(zhí)行了BridgeInterceptor的前置邏輯蔑歌,它處理了header信息,并添加了gzip支持揽碘。然后轉(zhuǎn)交請(qǐng)求給下一層次屠,并等待結(jié)果返回。
第四個(gè)執(zhí)行了CacheInterceptor的前置邏輯雳刺,它創(chuàng)建了緩存策略劫灶,如果可以返回緩存,或網(wǎng)絡(luò)有問題這直接返回掖桦。否則轉(zhuǎn)交請(qǐng)求給下一層本昏,并等待結(jié)果返回。
第五個(gè)執(zhí)行了ConnectInterceptor的前置邏輯枪汪,它構(gòu)建并建立了連接涌穆,然后轉(zhuǎn)交請(qǐng)求給下一層,并等待結(jié)果返回料饥。
第五個(gè)執(zhí)行了networkInterceptors的前置邏輯蒲犬,這里如果設(shè)置了,那么可以在請(qǐng)求發(fā)出前做最后的處理岸啡,然后轉(zhuǎn)交請(qǐng)求給下一層原叮,并等待結(jié)果返回。
第五個(gè)執(zhí)行了CallServerInterceptor的前置邏輯,這是最后一個(gè)Interceptor奋隶,它已經(jīng)拿到了客戶端設(shè)置的請(qǐng)求的所有配置擂送,并且連接已經(jīng)建立。在這里正式開始往網(wǎng)絡(luò)寫請(qǐng)求唯欣,并等待返回請(qǐng)求結(jié)果嘹吨。返回結(jié)果進(jìn)行一定的判斷處理后直接返回給上一層。
如果設(shè)置了networkInterceptors境氢,那么結(jié)果先在networkInterceptors的后置邏輯處理后再返回給ConnectInterceptor
ConnectInterceptor沒有后置邏輯蟀拷,直接返回給CacheInterceptor
CacheInterceptor的后置邏輯對(duì)返回結(jié)果進(jìn)行緩存后,然后返回給BridgeInterceptor
BridgeInterceptor的后置邏輯對(duì)返回結(jié)果進(jìn)行解壓縮萍聊,然后返回給RetryAndFollowUpInterceptor
RetryAndFollowUpInterceptor的后置邏輯對(duì)返回結(jié)果進(jìn)行判斷问芬,是否需要重定向,是否需要執(zhí)行重試邏輯寿桨,不需要?jiǎng)t返回請(qǐng)求結(jié)果
如果設(shè)置了自定義Interceptor此衅,那么會(huì)返回到這里,根據(jù)需求對(duì)結(jié)果進(jìn)行處理亭螟,然后最終返回給調(diào)用端挡鞍。