學習參考資料:OKHttp源碼解析??OKHttp源碼分析——攔截器??OKhttp完全解析-攔截器
上一篇大概記錄了一下OKHttp的整體結構設計,這里引用泡網的一張總體設計圖
上面這張就是OKHttp總體設計圖了,它主要是通過Dispatcher不斷從RequestQueue中取出請求(Call),根據是否已緩存調用Cache或 Network這兩類數據獲取接口之一,從內存緩存或是服務器取得請求的數據。該引擎有同步和異步請求,同步請求通過Call.execute()直接返 回當前的Response,而異步請求會把當前的請求Call.enqueue添加(AsyncCall)到請求隊列中,并通過回調(Callback) 的方式來獲取最后結果。
這里可以看到mOkHttpClient.newCall(rq).enqueue(newMyCallBack(parser) {});中的Call.enqueue其實就是最終會執行將一個Call轉換為一個AsyncCall添加到隊列中,這里的分發隊列,會在后續筆記中詳細介紹。
上一篇筆記中提到,AsyncCall繼承了NamedRunnable實現了它的抽象方法execute()
execute方法里面是調用了getResponseWithIntercepteorChain()方法獲取服務器的返回,然后調用getDispatcher().finish();通知任務分發器該任務已結束。
getResponseWithIntercepteorChain():顧名思義,通過這個攔截器鏈中的每一個攔截器之后得到服務器的返回結果。
看源碼中這個方法得知我們的猜想沒有錯,他就是一個構建了一個攔截器鏈,通過依次執行該攔截器鏈中的每一個攔截器最終得到服務器返回。
官方文檔的解釋:觀察,修改以及可能短路的請求輸出和響應請求的回來。通常情況下攔截器用來添加,移除或者轉換請求或者回應的頭部信息。
這個方法的實現其實就是將很多個攔截器包括框架內部的,用戶自定義的,統統放到一個攔截器數組里,創造這個RealInterceptorChain這個攔截器鏈,最后實現這個proceed()這個方法
通過源碼我們可以看到,這個proceed()方法中采用列表的形式追蹤攔截器,攔截器會被有序調用。
創建下一個攔截鏈。傳入index + 1使得下一個攔截器鏈只能從下一個攔截器開始訪問
執行索引為index的intercept方法,并將下一個攔截器鏈傳入該方法
? ? 通過官方文檔的描述以及源碼的分析,我們心中對攔截器大概有個理解印象了,下面,就記錄一下,不同的攔截器實現的不同方法:
1.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的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);