征服面試官:OkHttp 原理篇 掌握這篇面試題彙總,吊打面試官!
前言
如今面試中高階開發工程師崗位,OKhttp 原理是必問環節,只會使用已經無法滿足 Android 開發市場的需求,優秀的第三方框架原始碼剖析不僅能深度理解框架,也能對自己學習帶來很大的幫助。
本篇文章根據朋友反饋和親身經歷簡單整理的一些關於 Okhttp 常見面試題目。
1.Okhttp 基本實現原理
OkHttp 主要是通過 5 個攔截器和 3 個雙端佇列(2 個非同步佇列,1 個同步佇列)工作。內部實現通過一個責任鏈模式完成,將網路請求的各個階段封裝到各個鏈條中,實現了各層的解耦。
OkHttp 的底層是通過 Socket 傳送 HTTP 請求與接受響應,但是 OkHttp 實現了連線池的概念,即對於同一主機的多個請求,可以公用一個 Socket 連線,而不是每次傳送完 HTTP 請求就關閉底層的 Socket,這樣就實現了連線池的概念。而 OkHttp 對 Socket 的讀寫操作使用的 OkIo 庫進行了一層封裝。
執行流程:
-
通過構建者構建出OkHttpClient物件,再通過newCall方法獲得RealCall請求物件.
-
通過RealCall發起同步或非同步請求,而決定是非同步還是同步請求的是由執行緒分發器dispatcher來決定.
-
當發起同步請求時會將請求加入到同步佇列中依次執行,所以會阻塞UI執行緒,需要開啟子執行緒執行.
-
當發起非同步請求時會建立一個執行緒池,並且判斷請求佇列是否大於最大請求佇列64,請求主機數是否大於5,如果大於請求新增到非同步等待佇列中,否則新增到非同步執行佇列,並執行任務.
2.Okhttp 網路快取如何實現?
OKHttp 預設只支援 get 請求的快取。
- 第一次拿到響應後根據頭資訊決定是否快取。
- 下次請求時判斷是否存在本地快取,是否需要使用對比快取、封裝請求頭資訊等等。
- 如果快取失效或者需要對比快取則發出網路請求,否則使用本地快取。
3.Okhttp 網路連線怎麼實現複用?
HttpEngine 在發起請求之前,會先呼叫nextConnection()
來獲取一個Connection
物件,如果可以從ConnectionPool
中獲取一個Connection
物件,就不會新建,如果無法獲取,就會呼叫createnextConnection()
來新建一個Connection
物件,這就是 Okhttp 多路複用的核心,不像之前的網路框架,無論有沒有,都會新建Connection
物件。
4.Dispatcher 的功能是什麼?
Dispatcher中文是分發器的意思,和攔截器不同的是分發器不做事件處理,只做事件流向。他負責將每一次Requst進行分發,壓棧到自己的執行緒池,並通過呼叫者自己不同的方式進行非同步和同步處理。 通俗的講就是主要維護任務佇列的作用。
- 記錄同步任務、非同步任務及等待執行的非同步任務。
- 排程執行緒池管理非同步任務。
- 發起/取消網路請求 API:execute、enqueue、cancel。
Dispatcher 類,該類中維護了三個雙端佇列(Deque):
readyAsyncCalls:準備執行的非同步請求
runningAsyncCalls:正在執行的非同步請求
runningSyncCalls:正在執行的同步請求
OkHttp 設定了預設的最大併發請求量 maxRequests = 64 和單個 Host 主機支援的最大併發量 maxRequestsPerHost = 5
5.addInterceptor 與 addNetworkInterceptor 的區別?
二者通常的叫法為應用攔截器和網路攔截器,從整個責任鏈路來看,應用攔截器是最先執行的攔截器,也就是使用者自己設定request
屬性後的原始請求,而網路攔截器位於ConnectInterceptor
和CallServerInterceptor
之間,此時網路鏈路已經準備好,只等待傳送請求資料。
- 首先,應用攔截器在
RetryAndFollowUpInterceptor
和CacheInterceptor
之前,所以一旦發生錯誤重試或者網路重定向,網路攔截器可能執行多次,因為相當於進行了二次請求,但是應用攔截器永遠只會觸發一次。另外如果在CacheInterceptor
中命中了快取就不需要走網路請求了,因此會存在短路網路攔截器的情況。 - 其次,如上文提到除了
CallServerInterceptor
,每個攔截器都應該至少呼叫一次realChain.proceed
方法。實際上在應用攔截器這層可以多次呼叫proceed
方法(本地異常重試)或者不呼叫proceed
方法(中斷),但是網路攔截器這層連線已經準備好,可且僅可呼叫一次proceed
方法。 - 最後,從使用場景看,應用攔截器因為只會呼叫一次,通常用於統計客戶端的網路請求發起情況;而網路攔截器一次呼叫代表了一定會發起一次網路通訊,因此通常可用於統計網路鏈路上傳輸的資料。
6、Okhttp 攔截器的作用是什麼?
1、應用攔截器
拿到的是原始請求,可以新增一些自定義header、通用引數、引數加密、閘道器接入等等。
-
RetryAndFollowUpInterceptor 處理錯誤重試和重定向
-
BridgeInterceptor 應用層和網路層的橋接攔截器,主要工作是為請求新增cookie、新增固定的header,比如Host、Content-Length、Content-Type、User-Agent等等,然後儲存響應結果的cookie,如果響應使用gzip壓縮過,則還需要進行解壓。
-
CacheInterceptor 快取攔截器,如果命中快取則不會發起網路請求。
-
ConnectInterceptor 連線攔截器,內部會維護一個連線池,負責連線複用、建立連線(三次握手等等)、釋放連線以及建立連線上的socket流。
2、網路攔截器
使用者自定義攔截器,通常用於監控網路層的資料傳輸。
- CallServerInterceptor 請求攔截器,在前置準備工作完成後,真正發起了網路請求。
7、Okhttp 有哪些優勢?
- 支援 http2,對一臺機器的所有請求共享同一個 Socket
- 內建連線池,支援連線複用,減少延遲
- 支援透明的 gzip 壓縮響應體
- 響應快取可以完全避免網路重複請求
- 請求失敗時自動重試主機的其他 ip,自動重定向
- 豐富的 API,可擴充套件性好
8、response.body().string() 為什麼只能呼叫一次?
我們可能習慣在獲取到Response
物件後,先response.body().string()
列印一遍 Log,再進行資料解析,卻發現第二次直接拋異常,其實直接跟原始碼進去看就發現,通過source
拿到位元組流以後,直接呼叫closeQuietly()
方法關閉了,這樣第二次再去通過source
讀取就直接流已關閉的異常了。
public final String string() throws IOException {
BufferedSource source = source();
try {
Charset charset = Util.bomAwareCharset(source, charset());
return source.readString(charset);
} finally {
//這裡講resource給悄悄close了
Util.closeQuietly(source);
}
}
解決方案:1.記憶體快取一份response.body().string()
;2.自定義攔截器處理 Log。
9、Okhttp 運用了哪些設計模式?
Okhttp 運用了六種設計模式:
- 構造者模式(OkhttpClient,Request 等各種物件的建立)
- 工廠模式(在 Call 介面中,有一個內部工廠 Factory 介面。)
- 單例模式(Platform 類,已經使用 Okhttp 時使用單例)
- 策略模式(在 CacheInterceptor 中,在響應資料的選擇中使用了策略模式,選擇快取資料還是選擇網路訪問。)
- 責任鏈模式(攔截器的鏈式呼叫)
- 享元模式(Dispatcher 的執行緒池中,不限量的執行緒池實現了物件複用)
相關文章
- 吊打面試官——redis面試Redis
- Java 面試-吊打面試官系列 Redis 基礎Java面試Redis
- AQS很難,面試不會?看我一篇文章吊打面試官AQS面試
- 動畫:《大前端吊打面試官系列》 之原生 JavaScript 精華篇動畫前端面試JavaScript
- 【乾貨】Android 一線網際網路面試題彙總,13模組200+題,征服面試官不是夢!Android面試題
- 一文吃透Volatile,征服面試官面試
- 面試官的總結面試
- 《吊打面試官》系列-秒殺系統設計面試
- 吊打面試官!從多維度理解架構面試架構
- 吊打面試官!業務架構的關鍵概念面試架構
- 詢問面試官的面試問題面試
- 看完這篇 HashSet,跟面試官扯皮沒問題了面試
- 金三銀四,如何征服面試官,拿到Offer面試
- 面試 HTTP ,99% 的面試官都愛問這些問題面試HTTP
- 這15道MySQL面試題,解決了90%的面試官MySql面試題
- 吊打面試官!應用間互動如何設計?面試
- [面試倉庫]CSS面試題彙總--佈局篇CSS面試題
- 面試官十年面試經驗總結面試
- 如何面試你的面試官面試
- 看完這篇HTTP,跟面試官扯皮就沒問題了HTTP面試
- 面試時,你會問面試官哪些問題?面試
- 面試官:小夥子,能聊明白JMM給你SSP!我:嘚吧嘚吧一萬字,直接征服面試官!面試
- 面試流程——谷歌資深面試官經驗總結面試谷歌
- 怎麼進行一場好的面試:面試官篇面試
- 手撕面試官系列:BAT面試常問85題面試BAT
- 操蛋的面試官面試
- 面試官的心思面試
- 新晉面試官對近期面試的感想與總結面試
- 多年前端面試官的面試套路總結前端面試
- 吊打面試官!MySQL靈魂100問,你能答出多少?面試MySql
- Android JVM面試專題:阿里100%會問到的JVM,20道靈魂質問面試題解析,讓你吊打面試官AndroidJVM阿里面試題
- 面試官會問到的專案中的技術問題總彙面試
- java面試彙總:JVM篇!Java面試JVM
- iOS 面試題彙總iOS面試題
- mysql 面試題彙總MySql面試題
- vue面試題總彙Vue面試題
- java面試題彙總Java面試題
- LLM面試題彙總面試題