OKHttp框架圖:
OkHttp源碼大概流程
這個(gè)圖片是從拆輪子系列:拆 OkHttp纪吮,大神對Okhttp源碼分析俩檬,他分析得特別好,推薦是看的博文碾盟。我只是結(jié)合他的總結(jié)棚辽,然后總結(jié)成自己的東西,寫一下冰肴,希望可以對okhttp更進(jìn)一步了解屈藐。
源碼有很多地方值得我們?nèi)W(xué)習(xí)。
一熙尉、Builder模式
OKHttpClient联逻,Request,Response等大量的使用這個(gè)模式检痰,這些類都需要大量的參數(shù)遣妥,所以使用Builder模式是很好的設(shè)計(jì)
- 1、這個(gè)模式可以避免構(gòu)造方法需要傳入大量的參數(shù)攀细,相比使用setting的方式設(shè)置參數(shù)箫踩,使用Builder更加清晰。
- 2谭贪、如果有大量的參數(shù)境钟,可能會(huì)有多個(gè)構(gòu)造方法,有一些默認(rèn)的參數(shù)俭识,這樣很容易使用了不對的構(gòu)造方法慨削。
- 3、雖然增加了不少代碼量,但是客戶端的調(diào)用非常的清晰
Builer模式的分析
二缚态、使用隊(duì)列管理請求磁椒,實(shí)現(xiàn)高并發(fā)
相應(yīng)的類RealCall、Dispatcher
Dispatcher內(nèi)部管理了三個(gè)隊(duì)列
三個(gè)隊(duì)列
同時(shí)Dispatcher設(shè)置了最大請求數(shù)64玫芦,設(shè)置了最大Host5
使用Dispatcher的finished方法控制隊(duì)列
將線程管理浆熔、線程池放在Dispatcher里面進(jìn)行管理,RealCall桥帆、AsyncCall負(fù)責(zé)執(zhí)行的邏輯医增。
同步excute的調(diào)用
異步調(diào)用A'syncCall最后的調(diào)用
不論是同步還是異步灌具,最后都是調(diào)用getResponseWithInterceptorChain()
三乞娄、責(zé)任鏈模式
OKHttp把責(zé)任鏈模式設(shè)計(jì)在最核心的地方鼠证,每一個(gè)請求會(huì)有連接疚膊、請求、處理返回等等一系列的任務(wù)锌蓄。在OKHttp中已攔截器作為每個(gè)責(zé)任的任務(wù)Interceptor
Interceptor
然后關(guān)聯(lián)到Chain的鏈條上熬尺,在Interceptor的每個(gè)intercept中褂始,在執(zhí)行Chain的proceed方法夺欲,知道Chain中沒有任務(wù)跪帝。
getResponseWithInterceptorChain
Interceptors
Interceptors
3.1 RetryAndFollowUpInterceptor
重試重定向攔截器,不斷判斷返回?cái)?shù)據(jù)洁闰,有問題重試或者重定向
會(huì)判斷后面攔截器返回的response的值,看是否請求完成万细,或者需要重定向或者重試
RetryAndFollowUpInterceptor的詳細(xì)分析
3.2 BridgeInterceptor
Bridges from application code to network code. First it builds a network request from a *user request. Then it proceeds to call the network. Finally it builds a user response *from the network response.
將應(yīng)用代碼轉(zhuǎn)換成網(wǎng)絡(luò)代碼扑眉,對用戶發(fā)送請求的數(shù)據(jù)進(jìn)行校驗(yàn)并矯正;同時(shí)網(wǎng)絡(luò)請求返回的數(shù)據(jù)進(jìn)行處理赖钞,處理為用戶希望也是用戶能夠理解的數(shù)據(jù)腰素。
BridgeInterceptor源碼 主要看intercept方法
chain.proceed調(diào)用之前是對請求數(shù)據(jù)進(jìn)行轉(zhuǎn)換,調(diào)用之后是對請求返回?cái)?shù)據(jù)進(jìn)行轉(zhuǎn)換
3.3 CacheInterceptor 緩存攔截器
/** Serves requests from the cache and writes responses to the cache. */
讀取緩存和寫入更新緩存
緩存機(jī)制
3.4 ConnectInterceptor
ConnectInterceptor
看似簡單
StreamAllocation 分配流雪营,他實(shí)際上是在RetryAndFollowUpInterceptor中創(chuàng)建的弓千,那時(shí)候它負(fù)責(zé)把創(chuàng)建的對象傳給chain,如果需要重定向就會(huì)重新創(chuàng)建献起,在這個(gè)攔截器中洋访,從其中獲取連接,獲取編解碼器
RealConnection 真是連接谴餐,通過streamAllocation尋找可用連接
HttpCodec Http編解碼
別人詳細(xì)的分析
將獲取到的內(nèi)容傳給后續(xù)的攔截器姻政,獲取到返回之后直接返回給前面的攔截器,沒有做進(jìn)一步的處理岂嗓。
3.5 networkInterceptors
這些是在請求的時(shí)候設(shè)置的攔截器
3.6 CallServerInterceptor
最后一個(gè)攔截器汁展,也是最重要的攔截器,response就是在這個(gè)攔截器中通過網(wǎng)絡(luò)請求獲取到的。
@OverridepublicResponse intercept(Chain chain)throwsIOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
HttpCodec httpCodec = realChain.httpStream();
StreamAllocation streamAllocation = realChain.streamAllocation();
RealConnection connection = (RealConnection) realChain.connection();
Request request = realChain.request();
longsentRequestMillis = System.currentTimeMillis();
//寫入頭部
httpCodec.writeRequestHeaders(request);
Response.Builder responseBuilder =null;
//請求是否有body
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.
//頭部是否有100-continue食绿,有的話等待response
if("100-continue".equalsIgnoreCase(request.header("Expect"))) {
httpCodec.flushRequest();
responseBuilder = httpCodec.readResponseHeaders(true);
}
//沒有100-continue
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);
//寫入body
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();
}
}
//完成request寫入
httpCodec.finishRequest();
if(responseBuilder ==null) {
//讀取頭部侈咕,并返回response
responseBuilder = httpCodec.readResponseHeaders(false);
}
//創(chuàng)建response
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
intcode = response.code();
//根據(jù)類型更新response屬性
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();
}
//請求是否要求關(guān)閉連接
if("close".equalsIgnoreCase(response.request().header("Connection"))
||"close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
if((code ==204|| code ==205) && response.body().contentLength() >0) {
throw newProtocolException(
"HTTP "+ code +" had non-zero Content-Length: "+ response.body().contentLength());
}
return response;
}
繼續(xù)總結(jié)中......