Okhttp3原始碼完全解析

2021-09-11 04:29:25 字數 3898 閱讀 5915

上文已經說了,okhttp和retrofit是相輔相成的,retrofit是對okhttp的上層封裝,okhttp是http的底層實現。那麼,今天就來解析一下okhttp的原始碼。

});okhttp的使用如下,我們能夠看到,先是new了乙個okhttpclient,然後這個okhttpclient又new了乙個call,這個call執行了enqueue方法,這個方法得到請求的結果,是成功或失敗。

我們看一下enqueue方法,發現call是乙個介面,最終在realcall找到具體的實現,**如下。

@override public void enqueue(callback responsecallback) 

capturecallstacktrace();

eventlistener.callstart(this);

client.dispatcher().enqueue(new asynccall(responsecallback));

}

我們可以看到,最終是dispatcher執行這個enqueue,那麼我們就看一下這個diapatcher這個物件,再看一下它的enqueue方法。最終可以發現,是由executorservice來執行call。而這個executorservice傳入的物件是runnable,由此可以斷定,dispatcher這個類是用來做執行緒控制的。而且,邏輯**應該是由某個runnable介面的類來實現的。

synchronized void enqueue(asynccall call)  else 

}

這個enqueue傳入的物件是asyncall,看一下asynccall裡面的runnable方法,發現具體的實現是在execute裡面,execute實現如下。

@override protected void execute()  else 

} catch (ioexception e) else

} finally

}

從裡面可以看到,是網路相關邏輯的**,並且對網路結果做處理。最重要的**邏輯是在getresponsewithinterceptorchain()中。其實,這裡面就是就是okhttp的技術核心,也就是各種interceptor的實現。interceptor翻譯成中文就是***,同時,我們也可以自己加入***。還能自己決定***是放在開頭還是結尾。

首先,看一下getresponsewithinterceptorchain()的**

response getresponsewithinterceptorchain() throws ioexception 

interceptors.add(new callserverinterceptor(forwebsocket));

interceptor.chain chain = new realinterceptorchain(interceptors, null, null, null, 0,

originalrequest, this, eventlistener, client.connecttimeoutmillis(),

client.readtimeoutmillis(), client.writetimeoutmillis());

return chain.proceed(originalrequest);

}

可以看到,先是建立了乙個list,然後往裡面丟了幾個interceptor。然後建立了乙個chain物件,呼叫了它的proceed方法。要想理解okhttp的原始碼,最重要的就是要理解它的鏈式呼叫。

所謂鏈式呼叫,就是各個interceptors會依次呼叫自己的intercept()方法,這裡面會有三個步驟,先說第二步,第二步是呼叫chain.proceed()方法。把請求交給下乙個interceptor,呼叫它們的intercept()方法。那麼第一步,就是呼叫下乙個intercepter的前置工作,第三步就是對返回的response做後置工作。

簡單的說,這個請求和響應就是一條鏈,首先a先對request做自己的前置工作,然後交給b,b也對a傳過來的request做前置工作,然後交給c,c把request傳送到後台,後台返回response,然後這個response給b,b對這個response做後置工作,然後返回a,a再對返回的response做後置工作。如此,一次網路請求結束。

既然已經清楚了okhttp的鏈式呼叫,再來看一下各個***的作用。

client.interceptors()和client.networkinterceptors():  首先,這兩個***是沒有具體邏輯的,需要我們自己去實現,我們可以通過addinterceptor(interceptor)和ddnetworkinterceptor(interceptor)新增我們自定義的***,裡面可以實現我們需要的功功能。 另外,它們是集合,就表示可以新增不止乙個***。無論是client.interceptors()還是client.networkinterceptors()都可以新增多個。它們具體的區別我會在後文中描述。

retryandfollowupinterceptor: 負責重試和重定向的***。這個是有一定條件的,比如你符合某個異常,像routeexception、ioexception等,同時你又符合其它條件,比如是否允許重試等等。符合所有條件,才允許重試,像伺服器返回404這種,是不會進行重試的。其實內部就是乙個死迴圈,如果請求成功或不符合重試條件就跳出迴圈,釋放資源。否則就繼續迴圈。

bridgeinterceptor: 橋接的***,主要是負責和http相關的處理,比如新增 content-type、content-length 等請求頭。同時,它還可以對gzip格式的包進行處理。

cacheinterceptor: 快取的***。獲取快取的網路資料是在交給下乙個***前,如果不需要網路獲取並且快取的response不為空,就獲取快取資料。如果獲取了快取資料,後面的***就不會再執行。

connectinterceptor: 連線的***,裡面只有前置工作,沒有後置工作,因為連線都是建立在傳送請求之前的。如果是http會建立tcp連線,如果是https在tcp之上還會建立tls連線。

callserverinterceptor:負責實際網路請求的i/o操作,裡面主要是通過okio的一些api來實現。包括從socket中讀取資料和往sokcket中寫入資料

這個是我們工作中經常會用到的,也是面試中問的比較多的問題,到底是選用addinterceptor還是選用addnetworkinterceptor呢。

interceptor是在所有的***之前,可以進行最早的前置工作,也可以做最後的善後工作,一般可以在這裡面加入統一的header。而networkinterceptor是在callserverinterceptor之前,可以說是排在所有***之後,除了真正進行網路操作的callserverinterceptor。這裡面看到的資料是原始資料,比如body還沒有被gzip解壓等。

所以大多數情況下,我們會選用addinterceptor而不是addnetworkinterceptor。只有我們需要看原始資料的時候,我們才會需要使用addnetworkinterceptor。

至此,okhttp的原始碼大致架構已經解析完畢,當然,裡面還有更多具體的細節,就不一一描述了。

OkHttp3原始碼解析

compile com.squareup.okhttp3 okhttp 3.6.0 最新版本 okhttp的最底層是使用socket,而不是urlconnection,它通過platform的class.forname 反射獲得當前runtime使用的socket庫。okhttp3使用場景特點 資料...

OkHttp3原始碼解析(二)OkHttp基本流程

首先使用okhttp發起乙個非同步請求,以此先簡單分析okhttp的大致流程。okhttp使用 okhttp流程主要類 功能 使用建造者模式初始化連線池,dispatcher等,為了節約資源推薦使用單列模式建立okhttpclient物件,維護執行緒池比較耗資源。http請求所需的url,請求方法等...

OkHttp3原始碼(二) Request

request 是對http請求報文概念的具體實現 請求報文的結構圖 根據結構圖去閱讀原始碼能很好的理解某些屬性的真實意義。我們看一下原始碼。public final class request 返回設定的url 返回設定的方法 get或post public string method 返回所有的...