OkHttp( 3.9.0-SNAPSHOT)源碼解析

OkHttp源碼的samples的簡(jiǎn)單使用的示例:

public static void main(String... args) throws Exception{

OkHttpClient client=new OkHttpClient();

// Create request for remote resource.

Request request=new Request.Builder()

.url(ENDPOINT)

.build();

// Execute the request and retrieve the response.

Response response=client.newCall(request).execute();

// Deserialize HTTP response to concrete type.

ResponseBody body=response.body();

Listcontributors=CONTRIBUTORS_JSON_ADAPTER.fromJson(body.source());

body.close();

......

}

靜態(tài)常量

OkHttpClient開(kāi)始就定義了兩個(gè)靜態(tài)常量,這兩個(gè)常量是與協(xié)議相關(guān)分別是DEFAULT_CONNECTION_SPECS和DEFAULT_PROTOCOLS。

靜態(tài)代碼塊

接下來(lái)看OkHttpClient的static代碼塊主要就是創(chuàng)建了一個(gè)Internal的內(nèi)部類(lèi)對(duì)象。

接口

OkHttpClient實(shí)現(xiàn)了三個(gè)接口,分別是Cloneable,Call.Factory,WebSocket.Factory

重點(diǎn)在Call.Factory接口上,Call該接口的實(shí)例就是我么去執(zhí)行請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的對(duì)象,

Call中的主要方法

/** 返回該Call創(chuàng)建的Request請(qǐng)求對(duì)象 */

Request request();

/** 同步執(zhí)行請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù),返回服務(wù)端響應(yīng)結(jié)果*/

Response execute()throwsIOException;

/** 異步執(zhí)行請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的回調(diào)方法*/

void enqueue(Callback responseCallback);

/** 取消網(wǎng)絡(luò)請(qǐng)求*/

void cancel();

/** 判斷網(wǎng)絡(luò)請(qǐng)求是否被執(zhí)行了*/

boolean isExecuted();

/** 判斷網(wǎng)絡(luò)請(qǐng)求是否被取消了*/

boolean isCanceled();

/**clone該方法是Cloneable接口中的方法,意義在于創(chuàng)建一個(gè)相同的請(qǐng)求對(duì)象*/

Call clone();

/**Factory內(nèi)部接口就是創(chuàng)建Call的工廠(chǎng)接口,該接口定義的方法newCall需要傳入Request對(duì)象*/

interface Factory{

Call newCall(Request request);

}

成員變量

最重要的就是OkHttpClient,該類(lèi)的成員變量中6個(gè)成員變量進(jìn)行重點(diǎn)說(shuō)明的

final Dispatcher dispatcher;

final List?interceptors;

final List?networkInterceptors;

final EventListener.Factory eventListenerFactory;

final @Nullable Cache cache;?

final @Nullable InternalCache internalCache;

1、同步請(qǐng)求過(guò)程解析

Response response=client.newCall(request).execute(); 這句代碼執(zhí)行過(guò)程:

(1)client.newCall(request)

第一步:上面提到OkHttpClient的三個(gè)接口中有個(gè)Factory內(nèi)部接口(創(chuàng)建Call的工廠(chǎng)接口),而Call對(duì)象有個(gè)實(shí)現(xiàn)類(lèi)RealCall,其實(shí)newCall方法是RealCall執(zhí)行自己的newRealCall方法創(chuàng)建了一個(gè)RealCall實(shí)例,該方法三個(gè)參數(shù)如下:

*@param client OkHttpClient對(duì)象

*@param originalRequest 之前傳入的那個(gè)原始請(qǐng)求對(duì)象

*@param forWebSocket 是否是WebSocket

RealCall call=newRealCall(client,originalRequest,forWebSocket);

第二步:上面提到OkHttpClient的6個(gè)成員變量中有個(gè)EventListener.Factory eventListenerFactory對(duì)象(也是個(gè)工廠(chǎng)接口,內(nèi)部定義了一個(gè)create方法用于創(chuàng)建EventListener對(duì)象),上一步傳入了OkHttpClient對(duì)象,該對(duì)象已經(jīng)創(chuàng)建完了eventListenerFactory實(shí)例,所以拿到該實(shí)例傳入call對(duì)象創(chuàng)建EventListener對(duì)象。

抽象類(lèi)EventListener中有一大堆的網(wǎng)絡(luò)連接的監(jiān)聽(tīng)方法

call.eventListener=client.eventListenerFactory().create(call);

最后返回當(dāng)前的Call對(duì)象

(2)call.execute()

@Override

publicResponse execute()throwsIOException{

? ? synchronized(this) {

? ? if(executed)throw newIllegalStateException("Already Executed");

? ? ?executed=true;

}

? ?captureCallStackTrace();

?try{

? ? ? ?client.dispatcher().executed(this);

? ? ? Response result=getResponseWithInterceptorChain();

? ? ? if(result==null)throw newIOException("Canceled");

? ? ? ?returnresult;

? ? ? }finally{

? ? ? ?client.dispatcher().finished(this);

? ?}

}

2.1)call中的execute方法中的client.dispatcher().executed(this);

由于execute是同步執(zhí)行網(wǎng)絡(luò)請(qǐng)求所以要用關(guān)鍵字synchronized,

synchronized(this) {

? ? if(executed)throw newIllegalStateException("Already Executed");

? ?executed=true;

}

之后再執(zhí)行captureCallStackTrace()方法,放入堆棧進(jìn)行追蹤捕捉。

client.dispatcher()是獲得上面OkHttpClient的成員變量Dispatcher dispatcher,注意啦Dispatcher中的方法基本都是同步,用的Synchronized修飾的方法。為了分析清楚這里插一段Dispatcher的說(shuō)明。

Dispatcher中維護(hù)著執(zhí)行發(fā)送請(qǐng)求的線(xiàn)程池,所有的請(qǐng)求都是放在請(qǐng)求隊(duì)列中的總共有三個(gè)隊(duì)列readyAsyncCalls(準(zhǔn)備的異步請(qǐng)求隊(duì)列),runningAsyncCalls(正在在執(zhí)行的異步請(qǐng)求還包括被中斷的),runningSyncCalls(正在在執(zhí)行的異步請(qǐng)求還包括被中斷的)

private final Deque<AsyncCall> readyAsyncCalls=newArrayDeque<>();

private final Deque<AsyncCall> runningAsyncCalls=newArrayDeque<>();

private final Deque<RealCall> runningSyncCalls=newArrayDeque<>();

RealCall和AsyncCall的關(guān)系通過(guò)Dispatcher類(lèi)的導(dǎo)入代碼可以看出

import okhttp3.RealCall.AsyncCall; ? // AsyncCall其實(shí)就是RealCall的內(nèi)部類(lèi)

具體實(shí)現(xiàn)如下:

final class AsyncCall extends NamedRunnable{

private final Callback responseCallback;

// 構(gòu)造時(shí)需要傳入一個(gè)Callback接口,也就是返回給我們成功失敗的回調(diào)方法

AsyncCall(Callback responseCallback) { ?

? ?super("OkHttp %s",redactedUrl());

? ?this.responseCallback=responseCallback;

}

String host() {

? ? return originalRequest.url().host();

}

Request request() {

? ? ?return originalRequest;

}

RealCall ?get() {

? ? return RealCall.this;

}

@Override

protected void execute() {

? ? ? ? ? boolean signalledCallback=false;

? ?try{

? ? ? ? ? Response response=getResponseWithInterceptorChain();

? ? ? ? ? if(retryAndFollowUpInterceptor.isCanceled()) {

? ? ? ? ? signalledCallback=true;

? ? ? ? ? responseCallback.onFailure(RealCall.this,newIOException("Canceled"));

? ? ? }else{

? ? ? ? ? signalledCallback=true;

? ? ? ? ? responseCallback.onResponse(RealCall.this,response);

? ? ?}

? }catch(IOException e) {

? ? ? ?if(signalledCallback) {

? ? ? ?// Do not signal the callback twice!

? ? ? ? Platform.get().log(INFO,"Callback failure for "+toLoggableString(),e);

? ? }else{

? ? ? ?responseCallback.onFailure(RealCall.this,e);

? ?}

? ? ? }finally{

? ? ? ? client.dispatcher().finished(this);

? ? ? }

? ?}

}

dispatcher中erexecuted方法的具體實(shí)現(xiàn)

// ?加入同步執(zhí)行隊(duì)列

synchronized void executed(RealCall call) {

? runningSyncCalls.add(call);

}

2.2)Response result=getResponseWithInterceptorChain();

下面回過(guò)頭去看RealCall的execute方法中client.dispatcher().executed(this);執(zhí)行結(jié)束后的代碼Response result=getResponseWithInterceptorChain();

為了分析清楚這里插一段Interceptor的說(shuō)明

Response getResponseWithInterceptorChain()throwsIOException{

//創(chuàng)建一個(gè)存放攔截器的集合,最后傳入 newRealInterceptorChain對(duì)象中

? ?List<Intercepter> ?interceptors=newArrayList<>();

// client.interceptors() (自定義的攔截器, 在call api的前的攔截) - > //retryAndFollowUpInterceptor (實(shí)現(xiàn)請(qǐng)求重試)

? ?interceptors.addAll(client.interceptors());

// 重定向攔截器

? ?interceptors.add(retryAndFollowUpInterceptor);

// 橋接攔截器(處理header 、cookie 等)

? ?interceptors.add(newBridgeInterceptor(client.cookieJar()));

// 緩存攔截器(處理 cache)

? ?interceptors.add(newCacheInterceptor(client.internalCache()));

// 連接攔截器(負(fù)責(zé)建立連接)

? ?interceptors.add(newConnectInterceptor(client));

? ?if(!forWebSocket) {

// 自定義網(wǎng)絡(luò)攔截器(此時(shí)已建立連接)

? ? ?interceptors.addAll(client.networkInterceptors());

? }

// 服務(wù)請(qǐng)求攔截器(發(fā)起請(qǐng)求、接收響應(yīng))

? ?interceptors.add(newCallServerInterceptor(forWebSocket));

Interceptor.Chain chain = new RealInterceptorChain(interceptors,null,null,null,0,originalRequest,this,eventListener); ? return chain.proceed(originalRequest);

}?

上面的RealInterceptorChain方法具體實(shí)現(xiàn)。在RealCall里的getResponseWithInterceptorChain方法里,創(chuàng)建了一個(gè)RealInterceptorChain對(duì)象,調(diào)用proceed(),在interceptor的intercept()方法里又調(diào)用proceed(),明顯形成了一個(gè)遞歸,像鏈表一下一個(gè)一個(gè)遞歸傳遞并且做相應(yīng)的攔截處理。

RealInterceptorChain next=newRealInterceptorChain(interceptors,streamAllocation,httpCodec,

connection,index+1,request,call,eventListener);

Interceptor interceptor=interceptors.get(index);

Response response=interceptor.intercept(next);

最后一個(gè)攔截器返回處理的Response,也就是服務(wù)器端返回的結(jié)果,并且在代碼中加了許多的判斷如:this.httpCodec!=null 意思就是還沒(méi)有攔截鏈執(zhí)行完。interceptor必須執(zhí)行一次proceed()方法,否則會(huì)拋異常。

RealInterceptorChain + Interceptor實(shí)現(xiàn)了裝飾器模式,實(shí)現(xiàn)了請(qǐng)求/響應(yīng)的串式或流式處理。只不過(guò)內(nèi)層裝飾器不是外層裝飾器的成員變量,而是接口方法中創(chuàng)建的臨時(shí)變量。

在ConnectInterceptor之后的攔截器必須滿(mǎn)足:request的url要一致,interceptor必須執(zhí)行一次proceed()。這樣子做是為了保證遞推的正常運(yùn)作。而對(duì)與client.interceptors是在ConnectInterceptor之前的攔截器,可以不用必須執(zhí)行一次proceed()??梢詫?shí)現(xiàn)直接返回虛擬的response用于是測(cè)試等功能。

這幾個(gè)Interceptor的職責(zé):

RetryAndFollowUpInterceptor --->創(chuàng)建StreamAllocation對(duì)象,處理http的redirect,出錯(cuò)重試。對(duì)后續(xù)Interceptor的執(zhí)行的影響:修改request及StreamAllocation。

BridgeInterceptor-------------->補(bǔ)全缺失的一些http header。對(duì)后續(xù)Interceptor的執(zhí)行的影響:修改request。

CacheInterceptor-------------->處理http緩存。對(duì)后續(xù)Interceptor的執(zhí)行的影響:若緩存中有所需請(qǐng)求的響應(yīng),則后續(xù)Interceptor不再執(zhí)行。

ConnectInterceptor------------>借助于前面分配的StreamAllocation對(duì)象建立與服務(wù)器之間的連接,并選定交互所用的協(xié)議是HTTP 1.1還是HTTP 2。對(duì)后續(xù)Interceptor的執(zhí)行的影響:創(chuàng)建了httpStream和connection。

CallServerInterceptor----------->處理IO,與服務(wù)器進(jìn)行數(shù)據(jù)交換。對(duì)后續(xù)Interceptor的執(zhí)行的影響:為Interceptor鏈中的最后一個(gè)Interceptor,沒(méi)有后續(xù)Interceptor

2.3client.dispatcher().finished(this);?

dispatcher中finish方法的具體實(shí)現(xiàn)(注意第三個(gè)參數(shù)的差別)

/** Used by {@codeCall #execute} to signal completion.同步方法 */

void finished(RealCall call) {

? ? finished(runningSyncCalls,call,false);

}

/** Used by {@codeAsyncCall#run} to signal completion. 異步方法*/

void ?finished(AsyncCall call) {

? ? finished(runningAsyncCalls,call,true);

}

上面的finished(runningAsyncCalls,call,true);方法實(shí)現(xiàn)如下:

private?void finished(Dequecalls,T call,boolean promoteCalls) {

? ?int ?runningCallsCount;

? ?Runnable idleCallback;

? synchronized(this) {

? ? if (!calls.remove(call) ) throw newAssertionError("Call wasn't in-flight!");

? ? ? if(promoteCalls) ?promoteCalls(); // 異步Call數(shù)量多時(shí)需要維護(hù)隊(duì)列,而不是立即執(zhí).行,所以要加入到runningAsyncCalls中

? ? ? ?runningCallsCount = runningCallsCount();

? ? ? ?idleCallback = this.idleCallback;

? }

? if(runningCallsCount==0&&idleCallback!=null) {

? ? idleCallback.run();

? }

}

上面promoteCalls方法的具體實(shí)現(xiàn)如下:

private int maxRequests=64;

private int maxRequestsPerHost=5;

private void promoteCalls() {

? ? if(runningAsyncCalls.size()>=maxRequests) return;// 已經(jīng)達(dá)到最大容器.

? ? ?if ( readyAsyncCalls.isEmpty() ) return; // 隊(duì)列為空

? ? ? ? for(Iterator?i=readyAsyncCalls.iterator();i.hasNext();) { ?// 遍歷取出

? ? ? ? ? AsyncCall call=i.next(); ?

?// 當(dāng)正在執(zhí)行的任務(wù)總數(shù)及相同host下的任務(wù)數(shù)小于最大值時(shí),直接執(zhí)行當(dāng)前請(qǐng)求,而任務(wù)數(shù)超過(guò)限定時(shí),將其加入等待隊(duì)列。

? ? ? ? ? if ( runningCallsForHost(call) < maxRequestsPerHost ){?

? ? ? ? ? ? ?i.remove();

? ? ? ? ? ? runningAsyncCalls.add(call);

? ? ? ? ? ? executorService().execute(call);

? ? ? ? ? }

? ? ?}

? ? if ( runningAsyncCalls.size()>=maxRequests ) return;// Reached max capacity.

?}

}

還可以通setMaxRequests()設(shè)置同時(shí)允許執(zhí)行的最大請(qǐng)求數(shù),以及setMaxRequestsPerHost()設(shè)置相同host下最多運(yùn)行的請(qǐng)求數(shù)。從源碼中看出OkHttpClient用了許多的Budiler設(shè)計(jì)模式,幾個(gè)重要的類(lèi)Response、Request、OkHttpClient。

2、異步請(qǐng)求過(guò)程解析

RealCall的enqueue方法,其中遇到的大部分方法在同步請(qǐng)求中有分析就不贅述了。主要講一下異步網(wǎng)絡(luò)請(qǐng)求的流程

@Override

public voidenqueue(Callback responseCallback) {

? synchronized(this) {

? ? ? if(executed)throw newIllegalStateException("Already Executed"); ?

? ? ?executed=true;

?}

? ? captureCallStackTrace();

? ? client.dispatcher().enqueue(newAsyncCall(responseCallback));

}

上面client.dispatcher().enqueue(newAsyncCall(responseCallback));中Dispatcher的enqueue方法

synchronized void enqueue(AsyncCall call) {

// 如果正在執(zhí)行異步請(qǐng)求的隊(duì)列沒(méi)有超過(guò)最大請(qǐng)求數(shù)量,并且有沒(méi)有超過(guò)每個(gè)主機(jī)允許的最大訪(fǎng)問(wèn)量

// 就將請(qǐng)求加入到正在執(zhí)行異步請(qǐng)求的隊(duì)列中,否則就加入到準(zhǔn)備異步請(qǐng)求的隊(duì)列中去

? if(runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost

? ? ?runningAsyncCalls.add(call);?

? ? ?executorService().execute(call);

? ?}else{

? ? ? readyAsyncCalls.add(call);

? ?}


異步請(qǐng)求返回是通過(guò)接口回調(diào)的具體實(shí)現(xiàn)如下:

final classAsyncCallextendsNamedRunnable{

private finalCallback responseCallback;

AsyncCall(Callback responseCallback) {

? ? super("OkHttp %s",redactedUrl());

? ? this.responseCallback=responseCallback;

}

String host() {

? ? return ?originalRequest.url().host();

}

Request request() {

? return originalRequest;

}

RealCall get() {

? ? return ?RealCall.this;

}

@Override

protected voidexecute() {

? ?booleansignalledCallback=false;

try{

? ? Response response=getResponseWithInterceptorChain();

? ? if (retryAndFollowUpInterceptor.isCanceled() ) {

? ? ? ?signalledCallback=true;

? ? ? ?responseCallback.onFailure(RealCall.this,newIOException("Canceled"));

? ? }else{

? ? ? signalledCallback=true;

? ? ? responseCallback.onResponse(RealCall.this,response);

}

? }catch(IOException e) {

? ? ? ? if(signalledCallback) {

? ? ? ? ? // Do not signal the callback twice!

? ? ? ? ? Platform.get().log(INFO,"Callback failure for "+toLoggableString(),e);

? ? ? }else{

? ? ? ? ? responseCallback.onFailure(RealCall.this,e);

? ? ? ?}

? ?}finally{

? ? ?client.dispatcher().finished(this);

? ?}

?}

}

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

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

  • 這篇文章主要講 Android 網(wǎng)絡(luò)請(qǐng)求時(shí)所使用到的各個(gè)請(qǐng)求庫(kù)的關(guān)系,以及 OkHttp3 的介紹。(如理解有誤,...
    小莊bb閱讀 1,322評(píng)論 0 4
  • 這段時(shí)間老李的新公司要更換網(wǎng)絡(luò)層,知道現(xiàn)在主流網(wǎng)絡(luò)層的模式是RxJava+Retrofit+OKHttp,所以老李...
    隔壁老李頭閱讀 33,892評(píng)論 51 405
  • OkHttp作為時(shí)下最受歡迎的網(wǎng)絡(luò)請(qǐng)求框架之一,它有著自己的優(yōu)點(diǎn): 使用了眾多的設(shè)計(jì)模式(如:Builder模式、...
    永恒之眼V閱讀 344評(píng)論 1 1
  • OkHttp源碼分析-同步篇 很早就想拿okhttp開(kāi)刀了,這次就記一次使用OKhttp的網(wǎng)絡(luò)請(qǐng)求。首先需要說(shuō)明的...
    埃賽爾閱讀 1,055評(píng)論 1 2
  • 不知從什么時(shí)候開(kāi)始,我也開(kāi)始流入“曬朋友圈”的大潮,直到上個(gè)星期,拉開(kāi)相冊(cè)的小框,然后,便是腦海的一瞬空白。 ——...
    慧君慧君閱讀 933評(píng)論 0 1

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