九、Okhttp簡(jiǎn)析

獲取OkhttpClient實(shí)例的兩種方式

OkhttpClient client = new OkhttpClient()
OkhttpClient.Builder  build = new OkhttpClient.Builder()
build.writeTimeOut()/readTimeOut()/connectTimeOut()/cache()
OkhttpClient clinet  = bulid.build()

構(gòu)建請(qǐng)求

Requset request = new Request.Builder().url().bulid()
client.newCall(request).enqueue(new CallBack(){  
    onFailure()
    onResponse()
})

newCall方法里實(shí)際創(chuàng)建的是RealCall對(duì)象,調(diào)用了dispatcher.enqueue()方法,Dispatcher類用于任務(wù)調(diào)度控制并發(fā)請(qǐng)求,維護(hù)了幾個(gè)主要變量,最大并發(fā)請(qǐng)求數(shù),主機(jī)最大請(qǐng)求鏈接數(shù),消費(fèi)者線程池,將要運(yùn)行的異步請(qǐng)求隊(duì)列,正在執(zhí)行的異步請(qǐng)求隊(duì)列,正在執(zhí)行的同步請(qǐng)求隊(duì)列。
ReallCall方法中的enqueue方法實(shí)際調(diào)用的是Dispatcher的enqueue方法,在方法中會(huì)判斷當(dāng)前是否已達(dá)到最大并發(fā)請(qǐng)求數(shù),是否達(dá)到主機(jī)最大鏈接數(shù),如果為達(dá)到則加入正在運(yùn)行的異步請(qǐng)求隊(duì)列中,同時(shí)線程池進(jìn)行請(qǐng)求執(zhí)行,否則將請(qǐng)求加入將要執(zhí)行的異步請(qǐng)求隊(duì)列中。線程池中傳進(jìn)來的 參數(shù)是AsyncCall,它是RealCall的內(nèi)部類,其內(nèi)部也實(shí)現(xiàn)了execute方法,在其方法中finally中執(zhí)行了Dispather的finished方法,在其中會(huì)將執(zhí)行的request從runningAsyncCalls移除后執(zhí)行promoteCalls方法,進(jìn)行下一個(gè)request請(qǐng)求的處理,方法中判斷當(dāng)前最大請(qǐng)求鏈接數(shù)是否已經(jīng)達(dá)到,判斷ready隊(duì)列中是否還有未執(zhí)行請(qǐng)求,判斷主機(jī)的最大鏈接數(shù)是否已經(jīng)達(dá)到,未達(dá)到則將請(qǐng)求從ready隊(duì)列中移除并添加入running隊(duì)列中同時(shí)線程池執(zhí)行execute方法從而達(dá)到請(qǐng)求的不斷獲取判斷執(zhí)行過程。
在AsyncCall中的execute方法中會(huì)進(jìn)行真正的網(wǎng)絡(luò)請(qǐng)求獲取到Response對(duì)象,在過程中會(huì)對(duì)攔截器鏈進(jìn)行處理,getResponseWithInterceptorChain 方法中創(chuàng)建ApplicationInterceptorChain攔截器鏈。這個(gè) 類也是RealCall的內(nèi)部類,執(zhí)行了它的proceed方法進(jìn)行從攔截器列表中讀取攔截器進(jìn)行相應(yīng)的處理,在后面攔截器未處理完前,前邊的攔截器會(huì)處于阻塞狀態(tài),即攔截器是順序執(zhí)行后進(jìn)行網(wǎng)絡(luò)請(qǐng)求拿到請(qǐng)求結(jié)果后再調(diào)用攔截器順序執(zhí)行后最后返回最終的Response結(jié)果。

攔截器種類

RetryAndFollowUpInterceptor:重試重定向攔截器,會(huì)通過try catch 的方式catch到RouteException和IOException異常后進(jìn)行重試,通過獲取ResponseCode進(jìn)行相對(duì)應(yīng)的重定向處理。
BridgeInterceptor:橋接攔截器,主要對(duì)hader進(jìn)行設(shè)置補(bǔ)全。
CacherInterceptor:緩存攔截器,根據(jù)網(wǎng)絡(luò)情況以及是否有緩存進(jìn)行相應(yīng)的緩存邏輯處理。
ConnectInterceptor:連接攔截器,StreamAllocation用于連接計(jì)數(shù),他有兩個(gè)關(guān)鍵角色:RealConnection:真正建立Socket連接的對(duì)象,ConnectionPool:連接池,用來管理和復(fù)用Socket連接。ConnectInterceptor攔截器從攔截器鏈中獲取StreamAllocation對(duì)象,這個(gè)對(duì)象在第一個(gè)攔截器中創(chuàng)建,在ConnectInterceptor中才用到。
執(zhí)行StreamAllocation對(duì)象的newStream方法創(chuàng)建HttpCodec對(duì)象,用來編碼HTTP request和解碼HTTP response。newStream方法里面通過findConnection方法返回了一個(gè)RealConnection對(duì)象。StreamAllocation對(duì)象的connect方法拿到上面返回的RealConnection對(duì)象,這個(gè)RealConnection對(duì)象是用來進(jìn)行實(shí)際的網(wǎng)絡(luò)IO傳輸?shù)摹?br> CallServerInterceptor:請(qǐng)求服務(wù)器攔截器,完成HTTP協(xié)議報(bào)文的封裝和解析。獲取攔截器鏈中的HttpCodec、StreamAllocation、RealConnection對(duì)象。調(diào)用httpCodec.writeRequestHeaders(request)將請(qǐng)求頭寫入緩存。判斷是否有請(qǐng)求體,如果有,請(qǐng)求頭通過攜帶特殊字段 Expect:100-continue來詢問服務(wù)器是否愿意接受請(qǐng)求體。通過httpCodec.finishRequest()結(jié)束請(qǐng)求。通過responseBuilder構(gòu)建Response。返回Response。

OkHttp的復(fù)用連接池

鏈接池位于ConnectionPool其中定義了最大socket最大鏈接數(shù)5,keepAlive默認(rèn)5分鐘,線程池工作隊(duì)列,隊(duì)列使用的是無容量限制的SynchronousQueue,Deque雙向隊(duì)列用于維護(hù)RealConnection即Socket物理連接的包裝。RouteDatabase用于記錄鏈接失敗路線名單。在ConnectionPool類的構(gòu)造函數(shù)中定義了最大socket鏈接數(shù)為5,keepAlive時(shí)間為5分鐘。
ConnectionPool是在OkhttpClinet實(shí)例化的時(shí)候創(chuàng)建的:

public OkhttpClient(){
  this(new Builder())
  public Builder(){
    dispatcher = new Dispatcher()
    connection = new ConnectionPool()
  }
}

ConnectionPool提供了對(duì)Deque<RealConnection>的操作put,get,connectionBecameIdel移除鏈接,evictAll移除所有鏈接,RealConnection添加進(jìn)Deque之前會(huì)先進(jìn)行連接清理,主要邏輯在cleanupRunnalbe,他是一個(gè)Runnable接口實(shí)例,線程池進(jìn)行execute清理操作時(shí)會(huì)傳入cleanupRunnable在run方法中會(huì)調(diào)用cleanup方法,同時(shí)會(huì)計(jì)算出下一次執(zhí)行cleanup的方法的時(shí)間,從而實(shí)現(xiàn)循環(huán)執(zhí)行清理閑置連接。在cleanup方法中定義了四個(gè)變量用于進(jìn)行空閑鏈接數(shù)和活躍鏈接數(shù)的計(jì)數(shù)同時(shí)獲取閑置鏈接,主要根據(jù)StreamAllocation計(jì)數(shù)對(duì)象,通過反復(fù)執(zhí)行他的acquire和release操作來改變RealConnection中的List<Reference<StreamAllocation>>的大小從而得出連接是否閑置進(jìn)而進(jìn)行清除操作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容