okHttp小結(jié)

by hzwusibo? 20190504


常見問題一:簡述一下OkHttp

OkHttp已被谷歌加入到Android的源碼中。目前比較流行的Retrofit也是默認(rèn)使用OkHttp的。

支持http2,對一臺機(jī)器的所有請求共享同一個(gè)socket

內(nèi)置連接池,支持連接復(fù)用,減少延遲

支持透明的gzip壓縮響應(yīng)體

通過緩存避免重復(fù)的請求

請求失敗時(shí)自動重試主機(jī)的其他ip,自動重定向

好用的API

關(guān)于 HTTP2 和 HTTPS,這些你必須要知道

http://www.itdecent.cn/p/bf1db5c4d2d2

常見問題二:看過OkHttp的源碼嗎,簡單說一下

(一)、總體設(shè)計(jì)

第一,通過一個(gè)構(gòu)建者模式(Request.Builder)構(gòu)建所有的request;然后分發(fā)到Dispatcher(分發(fā)器);

第二,Dispatcher再把request分發(fā)到HttpEngine(真正干活的類)中,HttpEngine首先要看一下本次請求有沒有cache(緩存),如果有緩存,就從緩存中拿到信息,然后返回給response;如果沒有緩存,HttpEngine就把request分發(fā)到ConnectionPool(連接池)中;

第三,在ConnectionPool(連接池)中,通過Connection發(fā)送請求,通過Route(路由)和Platfrom(平臺),到達(dá)Server(Socket),獲取到Data,然后返回response。

(二)、流程圖

上面是OKHttp總體設(shè)計(jì)圖,主要是通過Diapatcher不斷從RequestQueue中取出請求(Call),根據(jù)是否已緩存調(diào)用Cache或Network這兩類數(shù)據(jù)獲取接口之一,從內(nèi)存緩存或是服務(wù)器取得請求的數(shù)據(jù)。該引擎有同步和異步請求,同步請求通過Call.execute()直接返回當(dāng)前的Response,而異步請求會把當(dāng)前的請求Call.enqueue添加(AsyncCall)到請求隊(duì)列中,并通過回調(diào)(Callback)的方式來獲取最后結(jié)果。

OkHttp使用教程

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html

Dispatcher線程池總結(jié)

1)調(diào)度線程池Disptcher實(shí)現(xiàn)了高并發(fā),低阻塞的實(shí)現(xiàn)?

2)采用Deque作為緩存,先進(jìn)先出的順序執(zhí)行?

3)任務(wù)在try/finally中調(diào)用了finished函數(shù),控制任務(wù)隊(duì)列的執(zhí)行順序,而不是采用鎖,減少了編碼復(fù)雜性提高性能。

Android面試題-OkHttp3源碼分析

https://blog.csdn.net/mwq384807683/article/details/71173442?locationNum=8&fps=1

OkHttp通過定義許多攔截器一步一步地對Request進(jìn)行攔截處理,直到請求返回網(wǎng)絡(luò)數(shù)據(jù),后面又倒過來,一步一步地對Response進(jìn)行攔截處理,最后攔截的結(jié)果就是回調(diào)的最終Response。

RealInterceptorChain的proceed方法,通過順序地傳入一個(gè)攔截器的集合,創(chuàng)建一個(gè)RealInterceptorChain,然后拿到之前OkHttp創(chuàng)建的各種攔截器,并調(diào)用其interrupt方法,并返回Response對象。其調(diào)用順序如下:

1)在配置 OkHttpClient 時(shí)設(shè)置的 interceptors;

2)負(fù)責(zé)失敗重試以及重定向的 RetryAndFollowUpInterceptor;

3)負(fù)責(zé)把用戶構(gòu)造的請求轉(zhuǎn)換為發(fā)送到服務(wù)器的請求、把服務(wù)器返回的響應(yīng)轉(zhuǎn)換為用戶友好的響應(yīng)的 BridgeInterceptor;

4)負(fù)責(zé)讀取緩存直接返回、更新緩存的 CacheInterceptor;

5)負(fù)責(zé)和服務(wù)器建立連接的 ConnectInterceptor;

6)配置 OkHttpClient 時(shí)設(shè)置的 networkInterceptors;

7)負(fù)責(zé)向服務(wù)器發(fā)送請求數(shù)據(jù)、從服務(wù)器讀取響應(yīng)數(shù)據(jù)的 CallServerInterceptor。

OkHttp的這種攔截器鏈采用的是責(zé)任鏈模式,這樣的好處是將請求的發(fā)送和處理分開,并且可以動態(tài)添加中間的處理方實(shí)現(xiàn)對請求的處理、短路等操作

責(zé)任鏈模式是一種對象的行為模式。在責(zé)任鏈模式里,很多對象由每一個(gè)對象對其下家的引用而連接起來形成一條鏈。請求在這個(gè)鏈上傳遞,直到鏈上的某一個(gè)對象決定處理此請求。發(fā)出這個(gè)請求的客戶端并不知道鏈上的哪一個(gè)對象最終處理這個(gè)請求,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織和分配責(zé)任。

可以看到 OkHttp 的線程池配置如下:

核心線程數(shù):0

最大線程數(shù):Iteger.MAX_VALUE,其實(shí)就是不限制

空閑線程?;顣r(shí)間:60s

任務(wù)隊(duì)列:SynchronousQueue,為有界隊(duì)列,且隊(duì)列大小為 0,不存 Runnable,只是用來進(jìn)行生產(chǎn)者和消費(fèi)者之間的傳遞任務(wù)。

是不是很眼熟?和我們在 Executors 使用的 緩存線程池的配置完全一樣,緩存線程池的代碼如下:

? ? public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {

? ? ? ? return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 60L, TimeUnit.SECONDS,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new SynchronousQueue<Runnable>(),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? threadFactory);

? ? }

所以 OkHttp 自己創(chuàng)建的這個(gè)線程池,和緩存線程池的區(qū)別,僅僅是修改了線程名。

我們簡要分析一下緩存線程池的運(yùn)行機(jī)制,進(jìn)入到 ThreadPoolExecutor 中的execute方法的源碼中,假設(shè)線程池處于運(yùn)行狀態(tài),會有這樣的流程:

新過來一個(gè)任務(wù),由于核心線程數(shù)為 0,不需要創(chuàng)建核心線程,所以嘗試加入任務(wù)隊(duì)列

如果線程池中有線程剛好空閑可以接收任務(wù),因?yàn)槿蝿?wù)隊(duì)列的類型是 SynchronousQueue,實(shí)際大小為 0,只做消費(fèi)者和生產(chǎn)者的中轉(zhuǎn)站,所以這時(shí)候,就可以入列成功,通過 SynchronousQueue 中轉(zhuǎn)任務(wù)給空閑的線程執(zhí)行。

如果當(dāng)前線程池所有線程工作飽和,會入列失敗。這時(shí)候 ThreadPoolExecutor 會調(diào)用addWorker(command, false)來創(chuàng)建并且啟動新線程。

這樣子,就會產(chǎn)生疑問,那么如果一次性同時(shí)發(fā)起大量的請求,不就會產(chǎn)生大量線程了?比如我一次性發(fā)起 100 個(gè)請求,那么是不是會發(fā)出 100 個(gè)線程?

是的,如果直接使用該線程池而沒有其他的策略的話,是有這樣的問題。

所以在 OkHttp 中線程池只是一個(gè)輔助作用,僅僅是用來做線程緩存,便于復(fù)用的。真正對這些請求的并發(fā)數(shù)量限制,執(zhí)行時(shí)機(jī)等等都是調(diào)度器 Dispatcher 承擔(dān)的。在 OkHttp 這里,線程池只是個(gè)帶緩存功能的執(zhí)行器,而真正的調(diào)度是外部包了一個(gè)調(diào)度策略的。

https://www.cnblogs.com/hankzhouAndroid/p/8710284.html

Retrofit

OkHttp和Retrofit的聯(lián)系

http://www.itdecent.cn/p/4d67fe493ebf

Retrofit負(fù)責(zé)請求的數(shù)據(jù)和請求的結(jié)果,使用接口的方式呈現(xiàn)(注解)。

OkHttp負(fù)責(zé)請求的過程。

RxJava負(fù)責(zé)異步,各種線程之間的切換。

Retrofit是Square開源的一款適用于Android網(wǎng)絡(luò)請求的框架。Retrofit底層是基于OkHttp實(shí)現(xiàn)的,與其他網(wǎng)絡(luò)框架不同的是,它更多使用運(yùn)行時(shí)注解的方式提供功能。

1.Retrofit優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

?? 可以配置不同HTTP client來實(shí)現(xiàn)網(wǎng)絡(luò)請求,如okhttp、httpclient等;

?? 請求的方法參數(shù)注解都可以定制;

?? 支持同步、異步和RxJava;

?? 解耦;

?? 可以配置不同的反序列化工具來解析數(shù)據(jù),如json、xml等;

?? 使用非常方便靈活;

2.Retrofit注解

Retrofit注解分為三大類,分別是HTTP請求方法注解(8種)、標(biāo)記類注解(3種)和參數(shù)類注解(11種)。

??HTTP請求方法注解:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP

??標(biāo)記類注解:FormUrlEncoded、Multipart、Streaming

??參數(shù)類注解:Headers、Header、Body、Field、FieldMap、Part、PartMap、Path、Query、QueryMap、Url

Retrofit底層對網(wǎng)絡(luò)的訪問默認(rèn)是基于okhttp,不過Retrofit非常適合于restful url格式的請求,更多使用注解的方式提供功能。

Retrofit框架網(wǎng)絡(luò)請求流程圖

網(wǎng)絡(luò)請求:APP發(fā)起網(wǎng)絡(luò)請求,Retrofit通過注解配置請求參數(shù)、Header、Url之后,通過OkHttp發(fā)生網(wǎng)絡(luò)請求給服務(wù)器。

服務(wù)器響應(yīng):服務(wù)器返回響應(yīng)數(shù)據(jù),OkHttp將數(shù)據(jù)傳遞給Retrofit,再把數(shù)據(jù)直接傳遞給APP,界面刷新反饋結(jié)果給用戶。

OkHttp和Retrofit都是網(wǎng)絡(luò)開源框架,但是他們之間的區(qū)別請不要混淆:

職責(zé)不同:

??Retrofit主要負(fù)責(zé)應(yīng)用層面的封裝,就是說主要面向開發(fā)者,方便使用,比如請求參數(shù),響應(yīng)數(shù)據(jù)的處理,錯誤處理等等。

??OkHttp主要負(fù)責(zé)socket部分的優(yōu)化,比如多路復(fù)用,buffer緩存,數(shù)據(jù)壓縮等等。

封裝不同:

??Retrofit封裝了具體的請求,線程切換以及數(shù)據(jù)轉(zhuǎn)換。

??OkHttp 是基于Http協(xié)議封裝的一套請求客戶端,雖然它也可以開線程,但根本上它更偏向真正的請求,跟HttpClient, HttpUrlConnection的職責(zé)是一樣的。

網(wǎng)上一般都推薦RxJava+Retrofit+OkHttp框架。

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

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

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