OKHttp源碼解析(二)——攔截器

學習參考資料:OKHttp源碼解析??OKHttp源碼分析——攔截器??OKhttp完全解析-攔截器

上一篇大概記錄了一下OKHttp的整體結構設計,這里引用泡網的一張總體設計圖

OKHttp總體設計

上面這張就是OKHttp總體設計圖了,它主要是通過Dispatcher不斷從RequestQueue中取出請求(Call),根據是否已緩存調用Cache或 Network這兩類數據獲取接口之一,從內存緩存或是服務器取得請求的數據。該引擎有同步和異步請求,同步請求通過Call.execute()直接返 回當前的Response,而異步請求會把當前的請求Call.enqueue添加(AsyncCall)到請求隊列中,并通過回調(Callback) 的方式來獲取最后結果。

enqueue隊列

這里可以看到mOkHttpClient.newCall(rq).enqueue(newMyCallBack(parser) {});中的Call.enqueue其實就是最終會執行將一個Call轉換為一個AsyncCall添加到隊列中,這里的分發隊列,會在后續筆記中詳細介紹。

上一篇筆記中提到,AsyncCall繼承了NamedRunnable實現了它的抽象方法execute()

execute

execute方法里面是調用了getResponseWithIntercepteorChain()方法獲取服務器的返回,然后調用getDispatcher().finish();通知任務分發器該任務已結束。

getResponseWithIntercepteorChain():顧名思義,通過這個攔截器鏈中的每一個攔截器之后得到服務器的返回結果。

看源碼中這個方法得知我們的猜想沒有錯,他就是一個構建了一個攔截器鏈,通過依次執行該攔截器鏈中的每一個攔截器最終得到服務器返回。

官方文檔的解釋:觀察,修改以及可能短路的請求輸出和響應請求的回來。通常情況下攔截器用來添加,移除或者轉換請求或者回應的頭部信息。

Intercepteor

這個方法的實現其實就是將很多個攔截器包括框架內部的,用戶自定義的,統統放到一個攔截器數組里,創造這個RealInterceptorChain這個攔截器鏈,最后實現這個proceed()這個方法

proceed

通過源碼我們可以看到,這個proceed()方法中采用列表的形式追蹤攔截器,攔截器會被有序調用

創建下一個攔截鏈。傳入index + 1使得下一個攔截器鏈只能從下一個攔截器開始訪問

執行索引為index的intercept方法,并將下一個攔截器鏈傳入該方法

? ? 通過官方文檔的描述以及源碼的分析,我們心中對攔截器大概有個理解印象了,下面,就記錄一下,不同的攔截器實現的不同方法:

1.RetryAndFollowUpInterceptor:負責失敗重試以及重定向

RetryAndFollowUpInterceptor

以此為例,可以看到一行很關鍵的代碼,response= ((RealInterceptorChain) chain).proceed(request, streamAllocation,null,null);

這行代碼就是執行下一個攔截器鏈的proceed方法。而我們知道在下一個攔截器鏈中又會執行下一個攔截器的intercept方法。所以整個執行鏈就在攔截器與攔截器鏈中交替執行,最終完成所有攔截器的操作。這也是OkHttp攔截器的鏈式執行邏輯。

一個攔截器的intercept方法所執行的邏輯大致分為三部分:

在發起請求前對request進行處理

調用下一個攔截器,獲取response

對response進行處理,返回給上一個攔截器

這就是OkHttp攔截器機制的核心邏輯。所以一個網絡請求實際上就是一個個攔截器執行其intercept方法的過程。而這其中除了用戶自定義的攔截器外還有幾個核心攔截器完成了網絡訪問的核心邏輯,按照先后順序依次是:

RetryAndFollowUpInterceptor

BridgeInterceptor

CacheInterceptor

ConnectIntercetot

CallServerInterceptor

RetryAndFollowUpInterceptor:如上文代碼所示,RetryAndFollowUpInterceptor負責兩部分邏輯:在網絡請求失敗后進行重試,當服務器返回當前請求需要進行重定向時直接發起新的請求,并在條件允許情況下復用當前連接

2.BridgeInterceptor :負責把用戶構造的請求轉換為發送到服務器的請求、把服務器返回的響應轉換為用戶友好的響應

BridgeInterceptor主要負責以下幾部分內容:1.設置內容長度,內容編碼 2.設置gzip壓縮,并在接收到內容后進行解壓。省去了應用層處理數據解壓的麻煩,3.添加cookie 4.設置其他報頭,如User-Agent,Host,Keep-alive等。其中Keep-Alive是實現多路復用的必要步驟

3.CacheInterceptor :負責讀取緩存直接返回、更新緩存

CacheInterceptor的職責很明確,就是負責Cache的管理:1.當網絡請求有符合要求的Cache時直接返回Cache;2.當服務器返回內容有改變時更新當前cache;3.如果當前cache失效,刪除

4.ConnectIntercetot:負責和服務器建立連接

ConnectInterceptor

ConnectInterceptor的intercept方法只有一行關鍵代碼:

RealConnection connection= streamAllocation.connection();

即為當前請求找到合適的連接,可能復用已有連接也可能是重新創建的連接,返回的連接由連接池負責決定。

5.CallServerInterceptor:負責向服務器發送請求數據、從服務器讀取響應數據

CallServerInterceptor負責向服務器發起真正的訪問請求,并在接收到服務器返回后讀取響應返回。

圖片及解釋來源:https://yq.aliyun.com/articles/78104?t=t1

最后補充一句,攔截器分為網絡攔截器和應用攔截器,注冊網絡攔截器和注冊應用攔截器很類似。只是通過networkInterceptors()方法取代了interceptore()方法。

注冊網絡攔截器:client.networkInterceptors().add(new xxxInterceptor);

注冊應用攔截器:client.interceptore().add(new xxxInterceptor);

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容