上文已經說了,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 返回所有的...