by hzwusibo? 20190504
常見問題一:簡述一下OkHttp
OkHttp已被谷歌加入到Android的源碼中。目前比較流行的Retrofit也是默認使用OkHttp的关拒。
支持http2沛豌,對一臺機器的所有請求共享同一個socket
內(nèi)置連接池,支持連接復用啃炸,減少延遲
支持透明的gzip壓縮響應體
通過緩存避免重復的請求
請求失敗時自動重試主機的其他ip铆隘,自動重定向
好用的API
關于 HTTP2 和 HTTPS,這些你必須要知道
http://www.reibang.com/p/bf1db5c4d2d2
常見問題二:看過OkHttp的源碼嗎南用,簡單說一下
(一)膀钠、總體設計
第一,通過一個構建者模式(Request.Builder)構建所有的request裹虫;然后分發(fā)到Dispatcher(分發(fā)器)肿嘲;
第二,Dispatcher再把request分發(fā)到HttpEngine(真正干活的類)中筑公,HttpEngine首先要看一下本次請求有沒有cache(緩存)雳窟,如果有緩存,就從緩存中拿到信息匣屡,然后返回給response封救;如果沒有緩存拇涤,HttpEngine就把request分發(fā)到ConnectionPool(連接池)中;
第三誉结,在ConnectionPool(連接池)中鹅士,通過Connection發(fā)送請求,通過Route(路由)和Platfrom(平臺)惩坑,到達Server(Socket),獲取到Data如绸,然后返回response。
(二)旭贬、流程圖
上面是OKHttp總體設計圖怔接,主要是通過Diapatcher不斷從RequestQueue中取出請求(Call),根據(jù)是否已緩存調(diào)用Cache或Network這兩類數(shù)據(jù)獲取接口之一稀轨,從內(nèi)存緩存或是服務器取得請求的數(shù)據(jù)扼脐。該引擎有同步和異步請求,同步請求通過Call.execute()直接返回當前的Response奋刽,而異步請求會把當前的請求Call.enqueue添加(AsyncCall)到請求隊列中瓦侮,并通過回調(diào)(Callback)的方式來獲取最后結果。
OkHttp使用教程
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html
Dispatcher線程池總結
1)調(diào)度線程池Disptcher實現(xiàn)了高并發(fā)佣谐,低阻塞的實現(xiàn)?
2)采用Deque作為緩存肚吏,先進先出的順序執(zhí)行?
3)任務在try/finally中調(diào)用了finished函數(shù),控制任務隊列的執(zhí)行順序狭魂,而不是采用鎖罚攀,減少了編碼復雜性提高性能。
Android面試題-OkHttp3源碼分析
https://blog.csdn.net/mwq384807683/article/details/71173442?locationNum=8&fps=1
OkHttp通過定義許多攔截器一步一步地對Request進行攔截處理雌澄,直到請求返回網(wǎng)絡數(shù)據(jù)斋泄,后面又倒過來,一步一步地對Response進行攔截處理镐牺,最后攔截的結果就是回調(diào)的最終Response炫掐。
RealInterceptorChain的proceed方法,通過順序地傳入一個攔截器的集合睬涧,創(chuàng)建一個RealInterceptorChain募胃,然后拿到之前OkHttp創(chuàng)建的各種攔截器,并調(diào)用其interrupt方法畦浓,并返回Response對象痹束。其調(diào)用順序如下:
1)在配置 OkHttpClient 時設置的 interceptors;
2)負責失敗重試以及重定向的 RetryAndFollowUpInterceptor宅粥;
3)負責把用戶構造的請求轉換為發(fā)送到服務器的請求参袱、把服務器返回的響應轉換為用戶友好的響應的 BridgeInterceptor;
4)負責讀取緩存直接返回、更新緩存的 CacheInterceptor抹蚀;
5)負責和服務器建立連接的 ConnectInterceptor剿牺;
6)配置 OkHttpClient 時設置的 networkInterceptors;
7)負責向服務器發(fā)送請求數(shù)據(jù)环壤、從服務器讀取響應數(shù)據(jù)的 CallServerInterceptor晒来。
OkHttp的這種攔截器鏈采用的是責任鏈模式,這樣的好處是將請求的發(fā)送和處理分開郑现,并且可以動態(tài)添加中間的處理方實現(xiàn)對請求的處理湃崩、短路等操作
責任鏈模式是一種對象的行為模式。在責任鏈模式里接箫,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈攒读。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求辛友。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求薄扁,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織和分配責任。
可以看到 OkHttp 的線程池配置如下:
核心線程數(shù):0
最大線程數(shù):Iteger.MAX_VALUE废累,其實就是不限制
空閑線程保活時間:60s
任務隊列:SynchronousQueue邑滨,為有界隊列,且隊列大小為 0匣距,不存 Runnable,只是用來進行生產(chǎn)者和消費者之間的傳遞任務乙各。
是不是很眼熟墨礁?和我們在 Executors 使用的 緩存線程池的配置完全一樣耳峦,緩存線程池的代碼如下:
? ? public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
? ? ? ? return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 60L, TimeUnit.SECONDS,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new SynchronousQueue<Runnable>(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? threadFactory);
? ? }
所以 OkHttp 自己創(chuàng)建的這個線程池焕毫,和緩存線程池的區(qū)別蹲坷,僅僅是修改了線程名。
我們簡要分析一下緩存線程池的運行機制邑飒,進入到 ThreadPoolExecutor 中的execute方法的源碼中循签,假設線程池處于運行狀態(tài),會有這樣的流程:
新過來一個任務县匠,由于核心線程數(shù)為 0,不需要創(chuàng)建核心線程汹来,所以嘗試加入任務隊列
如果線程池中有線程剛好空閑可以接收任務,因為任務隊列的類型是 SynchronousQueue兰粉,實際大小為 0,只做消費者和生產(chǎn)者的中轉站玖姑,所以這時候,就可以入列成功焰络,通過 SynchronousQueue 中轉任務給空閑的線程執(zhí)行。
如果當前線程池所有線程工作飽和甜孤,會入列失敗。這時候 ThreadPoolExecutor 會調(diào)用addWorker(command, false)來創(chuàng)建并且啟動新線程课蔬。
這樣子郊尝,就會產(chǎn)生疑問,那么如果一次性同時發(fā)起大量的請求流昏,不就會產(chǎn)生大量線程了?比如我一次性發(fā)起 100 個請求谚鄙,那么是不是會發(fā)出 100 個線程刁绒?
是的闷营,如果直接使用該線程池而沒有其他的策略的話知市,是有這樣的問題。
所以在 OkHttp 中線程池只是一個輔助作用嫂丙,僅僅是用來做線程緩存娘赴,便于復用的。真正對這些請求的并發(fā)數(shù)量限制跟啤,執(zhí)行時機等等都是調(diào)度器 Dispatcher 承擔的诽表。在 OkHttp 這里,線程池只是個帶緩存功能的執(zhí)行器袄简,而真正的調(diào)度是外部包了一個調(diào)度策略的议双。
https://www.cnblogs.com/hankzhouAndroid/p/8710284.html
Retrofit
OkHttp和Retrofit的聯(lián)系
http://www.reibang.com/p/4d67fe493ebf
Retrofit負責請求的數(shù)據(jù)和請求的結果,使用接口的方式呈現(xiàn)(注解)汞舱。
OkHttp負責請求的過程宗雇。
RxJava負責異步,各種線程之間的切換赔蒲。
Retrofit是Square開源的一款適用于Android網(wǎng)絡請求的框架。Retrofit底層是基于OkHttp實現(xiàn)的欢际,與其他網(wǎng)絡框架不同的是矾兜,它更多使用運行時注解的方式提供功能。
1.Retrofit優(yōu)缺點
優(yōu)點:
?? 可以配置不同HTTP client來實現(xiàn)網(wǎng)絡請求椅寺,如okhttp、httpclient等桐玻;
?? 請求的方法參數(shù)注解都可以定制荆萤;
?? 支持同步、異步和RxJava链韭;
?? 解耦;
?? 可以配置不同的反序列化工具來解析數(shù)據(jù),如json州邢、xml等褪子;
?? 使用非常方便靈活骗村;
2.Retrofit注解
Retrofit注解分為三大類胚股,分別是HTTP請求方法注解(8種)、標記類注解(3種)和參數(shù)類注解(11種)琅拌。
??HTTP請求方法注解:GET、POST刻坊、PUT党晋、DELETE谭胚、PATCH未玻、HEAD、OPTIONS旁趟、HTTP
??標記類注解:FormUrlEncoded舞终、Multipart、Streaming
??參數(shù)類注解:Headers敛劝、Header、Body蛾方、Field上陕、FieldMap、Part释簿、PartMap、Path煮纵、Query、QueryMap行疏、Url
Retrofit底層對網(wǎng)絡的訪問默認是基于okhttp,不過Retrofit非常適合于restful url格式的請求终息,更多使用注解的方式提供功能贞让。
Retrofit框架網(wǎng)絡請求流程圖
網(wǎng)絡請求:APP發(fā)起網(wǎng)絡請求,Retrofit通過注解配置請求參數(shù)休傍、Header、Url之后磨取,通過OkHttp發(fā)生網(wǎng)絡請求給服務器柴墩。
服務器響應:服務器返回響應數(shù)據(jù),OkHttp將數(shù)據(jù)傳遞給Retrofit江咳,再把數(shù)據(jù)直接傳遞給APP,界面刷新反饋結果給用戶歼指。
OkHttp和Retrofit都是網(wǎng)絡開源框架,但是他們之間的區(qū)別請不要混淆:
職責不同:
??Retrofit主要負責應用層面的封裝胀茵,就是說主要面向開發(fā)者挟阻,方便使用,比如請求參數(shù)附鸽,響應數(shù)據(jù)的處理,錯誤處理等等熄浓。
??OkHttp主要負責socket部分的優(yōu)化省撑,比如多路復用谎柄,buffer緩存惯雳,數(shù)據(jù)壓縮等等鸿摇。
封裝不同:
??Retrofit封裝了具體的請求,線程切換以及數(shù)據(jù)轉換拙吉。
??OkHttp 是基于Http協(xié)議封裝的一套請求客戶端,雖然它也可以開線程往史,但根本上它更偏向真正的請求佛舱,跟HttpClient, HttpUrlConnection的職責是一樣的。
網(wǎng)上一般都推薦RxJava+Retrofit+OkHttp框架请祖。