OkHttp源碼的samples的簡單使用的示例:
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開始就定義了兩個靜態(tài)常量激况,這兩個常量是與協(xié)議相關(guān)分別是DEFAULT_CONNECTION_SPECS和DEFAULT_PROTOCOLS呼巷。
靜態(tài)代碼塊
接下來看OkHttpClient的static代碼塊主要就是創(chuàng)建了一個Internal的內(nèi)部類對象。
接口
OkHttpClient實(shí)現(xiàn)了三個接口什往,分別是Cloneable,Call.Factory,WebSocket.Factory
重點(diǎn)在Call.Factory接口上,Call該接口的實(shí)例就是我么去執(zhí)行請求網(wǎng)絡(luò)數(shù)據(jù)的對象尊浓,
Call中的主要方法
/** 返回該Call創(chuàng)建的Request請求對象 */
Request request();
/** 同步執(zhí)行請求網(wǎng)絡(luò)數(shù)據(jù)斩箫,返回服務(wù)端響應(yīng)結(jié)果*/
Response execute()throwsIOException;
/** 異步執(zhí)行請求網(wǎng)絡(luò)數(shù)據(jù)的回調(diào)方法*/
void enqueue(Callback responseCallback);
/** 取消網(wǎng)絡(luò)請求*/
void cancel();
/** 判斷網(wǎng)絡(luò)請求是否被執(zhí)行了*/
boolean isExecuted();
/** 判斷網(wǎng)絡(luò)請求是否被取消了*/
boolean isCanceled();
/**clone該方法是Cloneable接口中的方法,意義在于創(chuàng)建一個相同的請求對象*/
Call clone();
/**Factory內(nèi)部接口就是創(chuàng)建Call的工廠接口,該接口定義的方法newCall需要傳入Request對象*/
interface Factory{
Call newCall(Request request);
}
成員變量
最重要的就是OkHttpClient城瞎,該類的成員變量中6個成員變量進(jìn)行重點(diǎn)說明的
final Dispatcher dispatcher;
final List?interceptors;
final List?networkInterceptors;
final EventListener.Factory eventListenerFactory;
final @Nullable Cache cache;?
final @Nullable InternalCache internalCache;
1、同步請求過程解析
Response response=client.newCall(request).execute(); 這句代碼執(zhí)行過程:
(1)client.newCall(request)
第一步:上面提到OkHttpClient的三個接口中有個Factory內(nèi)部接口(創(chuàng)建Call的工廠接口),而Call對象有個實(shí)現(xiàn)類RealCall疾瓮,其實(shí)newCall方法是RealCall執(zhí)行自己的newRealCall方法創(chuàng)建了一個RealCall實(shí)例脖镀,該方法三個參數(shù)如下:
*@param client OkHttpClient對象
*@param originalRequest 之前傳入的那個原始請求對象
*@param forWebSocket 是否是WebSocket
RealCall call=newRealCall(client,originalRequest,forWebSocket);
第二步:上面提到OkHttpClient的6個成員變量中有個EventListener.Factory eventListenerFactory對象(也是個工廠接口,內(nèi)部定義了一個create方法用于創(chuàng)建EventListener對象)狼电,上一步傳入了OkHttpClient對象蜒灰,該對象已經(jīng)創(chuàng)建完了eventListenerFactory實(shí)例,所以拿到該實(shí)例傳入call對象創(chuàng)建EventListener對象。
抽象類EventListener中有一大堆的網(wǎng)絡(luò)連接的監(jiān)聽方法
call.eventListener=client.eventListenerFactory().create(call);
最后返回當(dāng)前的Call對象
(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ò)請求所以要用關(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的說明。
Dispatcher中維護(hù)著執(zhí)行發(fā)送請求的線程池窿撬,所有的請求都是放在請求隊列中的總共有三個隊列readyAsyncCalls(準(zhǔn)備的異步請求隊列)启昧,runningAsyncCalls(正在在執(zhí)行的異步請求還包括被中斷的),runningSyncCalls(正在在執(zhí)行的異步請求還包括被中斷的)
private final Deque<AsyncCall> readyAsyncCalls=newArrayDeque<>();
private final Deque<AsyncCall> runningAsyncCalls=newArrayDeque<>();
private final Deque<RealCall> runningSyncCalls=newArrayDeque<>();
RealCall和AsyncCall的關(guān)系通過Dispatcher類的導(dǎo)入代碼可以看出
import okhttp3.RealCall.AsyncCall; ? // AsyncCall其實(shí)就是RealCall的內(nèi)部類
具體實(shí)現(xiàn)如下:
final class AsyncCall extends NamedRunnable{
private final Callback responseCallback;
// 構(gòu)造時需要傳入一個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í)行隊列
synchronized void executed(RealCall call) {
? runningSyncCalls.add(call);
}
(2.2)Response result=getResponseWithInterceptorChain();
下面回過頭去看RealCall的execute方法中client.dispatcher().executed(this);執(zhí)行結(jié)束后的代碼Response result=getResponseWithInterceptorChain();
為了分析清楚這里插一段Interceptor的說明
Response getResponseWithInterceptorChain()throwsIOException{
//創(chuàng)建一個存放攔截器的集合密末,最后傳入 newRealInterceptorChain對象中
? ?List<Intercepter> ?interceptors=newArrayList<>();
// client.interceptors() (自定義的攔截器, 在call api的前的攔截) - > //retryAndFollowUpInterceptor (實(shí)現(xiàn)請求重試)
? ?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ò)攔截器(此時已建立連接)
? ? ?interceptors.addAll(client.networkInterceptors());
? }
// 服務(wù)請求攔截器(發(fā)起請求跛璧、接收響應(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)建了一個RealInterceptorChain對象追城,調(diào)用proceed(),在interceptor的intercept()方法里又調(diào)用proceed()刹碾,明顯形成了一個遞歸,像鏈表一下一個一個遞歸傳遞并且做相應(yīng)的攔截處理座柱。
RealInterceptorChain next=newRealInterceptorChain(interceptors,streamAllocation,httpCodec,
connection,index+1,request,call,eventListener);
Interceptor interceptor=interceptors.get(index);
Response response=interceptor.intercept(next);
最后一個攔截器返回處理的Response,也就是服務(wù)器端返回的結(jié)果迷帜,并且在代碼中加了許多的判斷如:this.httpCodec!=null 意思就是還沒有攔截鏈執(zhí)行完物舒。interceptor必須執(zhí)行一次proceed()方法,否則會拋異常戏锹。
RealInterceptorChain + Interceptor實(shí)現(xiàn)了裝飾器模式冠胯,實(shí)現(xiàn)了請求/響應(yīng)的串式或流式處理。只不過內(nèi)層裝飾器不是外層裝飾器的成員變量锦针,而是接口方法中創(chuàng)建的臨時變量荠察。
在ConnectInterceptor之后的攔截器必須滿足:request的url要一致,interceptor必須執(zhí)行一次proceed()奈搜。這樣子做是為了保證遞推的正常運(yùn)作悉盆。而對與client.interceptors是在ConnectInterceptor之前的攔截器,可以不用必須執(zhí)行一次proceed()媚污∫ㄆ埃可以實(shí)現(xiàn)直接返回虛擬的response用于是測試等功能。
這幾個Interceptor的職責(zé):
RetryAndFollowUpInterceptor --->創(chuàng)建StreamAllocation對象耗美,處理http的redirect京髓,出錯重試。對后續(xù)Interceptor的執(zhí)行的影響:修改request及StreamAllocation商架。
BridgeInterceptor-------------->補(bǔ)全缺失的一些http header堰怨。對后續(xù)Interceptor的執(zhí)行的影響:修改request。
CacheInterceptor-------------->處理http緩存蛇摸。對后續(xù)Interceptor的執(zhí)行的影響:若緩存中有所需請求的響應(yīng)备图,則后續(xù)Interceptor不再執(zhí)行。
ConnectInterceptor------------>借助于前面分配的StreamAllocation對象建立與服務(wù)器之間的連接赶袄,并選定交互所用的協(xié)議是HTTP 1.1還是HTTP 2揽涮。對后續(xù)Interceptor的執(zhí)行的影響:創(chuàng)建了httpStream和connection。
CallServerInterceptor----------->處理IO饿肺,與服務(wù)器進(jìn)行數(shù)據(jù)交換蒋困。對后續(xù)Interceptor的執(zhí)行的影響:為Interceptor鏈中的最后一個Interceptor,沒有后續(xù)Interceptor
(2.3)client.dispatcher().finished(this);?
dispatcher中finish方法的具體實(shí)現(xiàn)(注意第三個參數(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ù)量多時需要維護(hù)隊列敬辣,而不是立即執(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; // 隊列為空
? ? ? ? for(Iterator?i=readyAsyncCalls.iterator();i.hasNext();) { ?// 遍歷取出
? ? ? ? ? AsyncCall call=i.next(); ?
?// 當(dāng)正在執(zhí)行的任務(wù)總數(shù)及相同host下的任務(wù)數(shù)小于最大值時,直接執(zhí)行當(dāng)前請求溉跃,而任務(wù)數(shù)超過限定時村刨,將其加入等待隊列。
? ? ? ? ? if ( runningCallsForHost(call) < maxRequestsPerHost ){?
? ? ? ? ? ? ?i.remove();
? ? ? ? ? ? runningAsyncCalls.add(call);
? ? ? ? ? ? executorService().execute(call);
? ? ? ? ? }
? ? ?}
? ? if ( runningAsyncCalls.size()>=maxRequests ) return;// Reached max capacity.
?}
}
還可以通setMaxRequests()設(shè)置同時允許執(zhí)行的最大請求數(shù)撰茎,以及setMaxRequestsPerHost()設(shè)置相同host下最多運(yùn)行的請求數(shù)嵌牺。從源碼中看出OkHttpClient用了許多的Budiler設(shè)計模式,幾個重要的類Response、Request髓梅、OkHttpClient拟蜻。
2、異步請求過程解析
RealCall的enqueue方法枯饿,其中遇到的大部分方法在同步請求中有分析就不贅述了酝锅。主要講一下異步網(wǎng)絡(luò)請求的流程
@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í)行異步請求的隊列沒有超過最大請求數(shù)量,并且有沒有超過每個主機(jī)允許的最大訪問量
// 就將請求加入到正在執(zhí)行異步請求的隊列中奢方,否則就加入到準(zhǔn)備異步請求的隊列中去
? if(runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost
? ? ?runningAsyncCalls.add(call);?
? ? ?executorService().execute(call);
? ?}else{
? ? ? readyAsyncCalls.add(call);
? ?}
異步請求返回是通過接口回調(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);
? ?}
?}
}