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();
......
}
靜態常量
OkHttpClient開始就定義了兩個靜態常量,這兩個常量是與協議相關分別是DEFAULT_CONNECTION_SPECS和DEFAULT_PROTOCOLS。
靜態代碼塊
接下來看OkHttpClient的static代碼塊主要就是創建了一個Internal的內部類對象。
接口
OkHttpClient實現了三個接口,分別是Cloneable,Call.Factory,WebSocket.Factory
重點在Call.Factory接口上,Call該接口的實例就是我么去執行請求網絡數據的對象,
Call中的主要方法
/** 返回該Call創建的Request請求對象 */
Request request();
/** 同步執行請求網絡數據,返回服務端響應結果*/
Response execute()throwsIOException;
/** 異步執行請求網絡數據的回調方法*/
void enqueue(Callback responseCallback);
/** 取消網絡請求*/
void cancel();
/** 判斷網絡請求是否被執行了*/
boolean isExecuted();
/** 判斷網絡請求是否被取消了*/
boolean isCanceled();
/**clone該方法是Cloneable接口中的方法,意義在于創建一個相同的請求對象*/
Call clone();
/**Factory內部接口就是創建Call的工廠接口,該接口定義的方法newCall需要傳入Request對象*/
interface Factory{
Call newCall(Request request);
}
成員變量
最重要的就是OkHttpClient,該類的成員變量中6個成員變量進行重點說明的
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(); 這句代碼執行過程:
(1)client.newCall(request)
第一步:上面提到OkHttpClient的三個接口中有個Factory內部接口(創建Call的工廠接口),而Call對象有個實現類RealCall,其實newCall方法是RealCall執行自己的newRealCall方法創建了一個RealCall實例,該方法三個參數如下:
*@param client OkHttpClient對象
*@param originalRequest 之前傳入的那個原始請求對象
*@param forWebSocket 是否是WebSocket
RealCall call=newRealCall(client,originalRequest,forWebSocket);
第二步:上面提到OkHttpClient的6個成員變量中有個EventListener.Factory eventListenerFactory對象(也是個工廠接口,內部定義了一個create方法用于創建EventListener對象),上一步傳入了OkHttpClient對象,該對象已經創建完了eventListenerFactory實例,所以拿到該實例傳入call對象創建EventListener對象。
抽象類EventListener中有一大堆的網絡連接的監聽方法
call.eventListener=client.eventListenerFactory().create(call);
最后返回當前的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是同步執行網絡請求所以要用關鍵字synchronized,
synchronized(this) {
? ? if(executed)throw newIllegalStateException("Already Executed");
? ?executed=true;
}
之后再執行captureCallStackTrace()方法,放入堆棧進行追蹤捕捉。
client.dispatcher()是獲得上面OkHttpClient的成員變量Dispatcher dispatcher,注意啦Dispatcher中的方法基本都是同步,用的Synchronized修飾的方法。為了分析清楚這里插一段Dispatcher的說明。
Dispatcher中維護著執行發送請求的線程池,所有的請求都是放在請求隊列中的總共有三個隊列readyAsyncCalls(準備的異步請求隊列),runningAsyncCalls(正在在執行的異步請求還包括被中斷的),runningSyncCalls(正在在執行的異步請求還包括被中斷的)
private final Deque<AsyncCall> readyAsyncCalls=newArrayDeque<>();
private final Deque<AsyncCall> runningAsyncCalls=newArrayDeque<>();
private final Deque<RealCall> runningSyncCalls=newArrayDeque<>();
RealCall和AsyncCall的關系通過Dispatcher類的導入代碼可以看出
import okhttp3.RealCall.AsyncCall; ? // AsyncCall其實就是RealCall的內部類
具體實現如下:
final class AsyncCall extends NamedRunnable{
private final Callback responseCallback;
// 構造時需要傳入一個Callback接口,也就是返回給我們成功失敗的回調方法
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方法的具體實現
// ?加入同步執行隊列
synchronized void executed(RealCall call) {
? runningSyncCalls.add(call);
}
(2.2)Response result=getResponseWithInterceptorChain();
下面回過頭去看RealCall的execute方法中client.dispatcher().executed(this);執行結束后的代碼Response result=getResponseWithInterceptorChain();
為了分析清楚這里插一段Interceptor的說明
Response getResponseWithInterceptorChain()throwsIOException{
//創建一個存放攔截器的集合,最后傳入 newRealInterceptorChain對象中
? ?List<Intercepter> ?interceptors=newArrayList<>();
// client.interceptors() (自定義的攔截器, 在call api的前的攔截) - > //retryAndFollowUpInterceptor (實現請求重試)
? ?interceptors.addAll(client.interceptors());
// 重定向攔截器
? ?interceptors.add(retryAndFollowUpInterceptor);
// 橋接攔截器(處理header 、cookie 等)
? ?interceptors.add(newBridgeInterceptor(client.cookieJar()));
// 緩存攔截器(處理 cache)
? ?interceptors.add(newCacheInterceptor(client.internalCache()));
// 連接攔截器(負責建立連接)
? ?interceptors.add(newConnectInterceptor(client));
? ?if(!forWebSocket) {
// 自定義網絡攔截器(此時已建立連接)
? ? ?interceptors.addAll(client.networkInterceptors());
? }
// 服務請求攔截器(發起請求、接收響應)
? ?interceptors.add(newCallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors,null,null,null,0,originalRequest,this,eventListener); ? return chain.proceed(originalRequest);
}?
上面的RealInterceptorChain方法具體實現。在RealCall里的getResponseWithInterceptorChain方法里,創建了一個RealInterceptorChain對象,調用proceed(),在interceptor的intercept()方法里又調用proceed(),明顯形成了一個遞歸,像鏈表一下一個一個遞歸傳遞并且做相應的攔截處理。
RealInterceptorChain next=newRealInterceptorChain(interceptors,streamAllocation,httpCodec,
connection,index+1,request,call,eventListener);
Interceptor interceptor=interceptors.get(index);
Response response=interceptor.intercept(next);
最后一個攔截器返回處理的Response,也就是服務器端返回的結果,并且在代碼中加了許多的判斷如:this.httpCodec!=null 意思就是還沒有攔截鏈執行完。interceptor必須執行一次proceed()方法,否則會拋異常。
RealInterceptorChain + Interceptor實現了裝飾器模式,實現了請求/響應的串式或流式處理。只不過內層裝飾器不是外層裝飾器的成員變量,而是接口方法中創建的臨時變量。
在ConnectInterceptor之后的攔截器必須滿足:request的url要一致,interceptor必須執行一次proceed()。這樣子做是為了保證遞推的正常運作。而對與client.interceptors是在ConnectInterceptor之前的攔截器,可以不用必須執行一次proceed()。可以實現直接返回虛擬的response用于是測試等功能。
這幾個Interceptor的職責:
RetryAndFollowUpInterceptor --->創建StreamAllocation對象,處理http的redirect,出錯重試。對后續Interceptor的執行的影響:修改request及StreamAllocation。
BridgeInterceptor-------------->補全缺失的一些http header。對后續Interceptor的執行的影響:修改request。
CacheInterceptor-------------->處理http緩存。對后續Interceptor的執行的影響:若緩存中有所需請求的響應,則后續Interceptor不再執行。
ConnectInterceptor------------>借助于前面分配的StreamAllocation對象建立與服務器之間的連接,并選定交互所用的協議是HTTP 1.1還是HTTP 2。對后續Interceptor的執行的影響:創建了httpStream和connection。
CallServerInterceptor----------->處理IO,與服務器進行數據交換。對后續Interceptor的執行的影響:為Interceptor鏈中的最后一個Interceptor,沒有后續Interceptor
(2.3)client.dispatcher().finished(this);?
dispatcher中finish方法的具體實現(注意第三個參數的差別)
/** 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);方法實現如下:
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數量多時需要維護隊列,而不是立即執.行,所以要加入到runningAsyncCalls中
? ? ? ?runningCallsCount = runningCallsCount();
? ? ? ?idleCallback = this.idleCallback;
? }
? if(runningCallsCount==0&&idleCallback!=null) {
? ? idleCallback.run();
? }
}
上面promoteCalls方法的具體實現如下:
private int maxRequests=64;
private int maxRequestsPerHost=5;
private void promoteCalls() {
? ? if(runningAsyncCalls.size()>=maxRequests) return;// 已經達到最大容器.
? ? ?if ( readyAsyncCalls.isEmpty() ) return; // 隊列為空
? ? ? ? for(Iterator?i=readyAsyncCalls.iterator();i.hasNext();) { ?// 遍歷取出
? ? ? ? ? AsyncCall call=i.next(); ?
?// 當正在執行的任務總數及相同host下的任務數小于最大值時,直接執行當前請求,而任務數超過限定時,將其加入等待隊列。
? ? ? ? ? if ( runningCallsForHost(call) < maxRequestsPerHost ){?
? ? ? ? ? ? ?i.remove();
? ? ? ? ? ? runningAsyncCalls.add(call);
? ? ? ? ? ? executorService().execute(call);
? ? ? ? ? }
? ? ?}
? ? if ( runningAsyncCalls.size()>=maxRequests ) return;// Reached max capacity.
?}
}
還可以通setMaxRequests()設置同時允許執行的最大請求數,以及setMaxRequestsPerHost()設置相同host下最多運行的請求數。從源碼中看出OkHttpClient用了許多的Budiler設計模式,幾個重要的類Response、Request、OkHttpClient。
2、異步請求過程解析
RealCall的enqueue方法,其中遇到的大部分方法在同步請求中有分析就不贅述了。主要講一下異步網絡請求的流程
@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) {
// 如果正在執行異步請求的隊列沒有超過最大請求數量,并且有沒有超過每個主機允許的最大訪問量
// 就將請求加入到正在執行異步請求的隊列中,否則就加入到準備異步請求的隊列中去
? if(runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost
? ? ?runningAsyncCalls.add(call);?
? ? ?executorService().execute(call);
? ?}else{
? ? ? readyAsyncCalls.add(call);
? ?}
異步請求返回是通過接口回調的具體實現如下:
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);
? ?}
?}
}