newCall分析
Call初始化
我們首先看一下在哪用到了Call:
final Call call = okHttpClient.newCall(request);
複制
想起來了吧?無論是get還是post請求 都要生成call對象,在上面我們發現call執行個體需要一個
okHttpClient
與
request
執行個體 ,我們先點進Call類去看看:
public interface Call extends Cloneable {
//請求
Request request();
//同步
Response execute() throws IOException;
//異步
void enqueue(Callback responseCallback);
//取消請求
void cancel();
//是否在請求過程中
boolean isExecuted();
//是否取消
boolean isCanceled();
Call clone();
//工廠接口
interface Factory {
Call newCall(Request request);
}
}
複制
我們發現Call是個接口, 并定義了一些方方法(方法含義在注釋上)。
我們繼續看
newCal()
方法
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
複制
繼續點選
newRealCall()
去:
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
複制
從代碼中我們發現在
newRealCall()
中初始化了
RealCall
,
RealCall
中初始化了
retryAndFollowUpInterceptor
:
- client: OkHttpClient 執行個體
- originalRequest : 最初的Request
- forWebSocket :是否支援websocket通信
- retryAndFollowUpInterceptor 從字面意思來說, 是重試和重定向攔截器 ,至于它有什麼作用我們繼續往下看
同步請求分析
Response response = call.execute();
複制
我們點進
execute()
中檢視:
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
複制
從上面代碼得知步驟:
(1).通過
synchronized
保證線程同步,判斷是否已經執行過 ,如果是直接抛異常
(2).
captureCallStackTrace();
字面意思:捕獲調用堆棧跟蹤,我們通過源碼發現裡面涉及到了
retryAndFollowUpInterceptor
(3).
eventListener
回調
CallStart()
(4).
client.dispatcher().executed(this);
看到了
dispatcher
是不是很熟悉?之前在分析
okhttpClient
初始化的時候遇到了,我們點選
executed()
方法進去:
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
複制
發現把我們傳進來的
realcall
放到了
runningSyncCalls
隊列中,從字面意思來說就是正在運作的同步的調用隊列中,為什麼說是隊列呢? :
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
複制
Deque即雙端隊列。是一種具有隊列和棧的性質的資料結構。雙端隊列中的元素可以從兩端彈出,相比list增加[]運算符重載。
(5).我們回到
execute()
繼續往下分析,剩下的代碼我們提取出三行代碼:
-
生成一個Response 執行個體equesr result = getResponseWithInterceptorChain();
-
:eventListener的callFailed回調eventListener.callFailed(this, e);
-
:dispatcher執行個體的finished方法client.dispatcher().finished(this);
不難看出,
getResponseWithInterceptorChain()
一定是此方法中的核心,字面意思是擷取攔截器鍊的響應,這就明白了,就是通過攔截器鍊處理後傳回Response

getResponseWithInterceptorChain() 分析
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors()); //自定義
interceptors.add(retryAndFollowUpInterceptor); //錯誤與跟蹤攔截器
interceptors.add(new BridgeInterceptor(client.cookieJar())); //橋攔截器
interceptors.add(new CacheInterceptor(client.internalCache())); //緩存攔截器
interceptors.add(new ConnectInterceptor(client)); //連接配接攔截器
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors()); //網絡攔截器
}
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);
}
複制
從上面代碼不難看出, 對最初的request做了層層攔截,每個攔截器的原理我們放在以後的章節去講, 這裡就不展開了!
這裡需要強調的一下
interceptors.addAll(client.interceptors());
,
client.interceptors()
是我們自定義的攔截器 它是在哪定義的?如何添加?我們去OkHttpClient類中發現:
可以通過初始化
okHttpClient
執行個體
.addInterceptor
的形式 添加。
異步請求分析
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("okhttp_error",e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Gson gson=new Gson();
Log.d("okhttp_success",response.body().string());
}
});
複制
點選
enqueue()
檢視:
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
複制
(1).通過
synchronized
保證線程同步,判斷是否已經執行過 ,如果是直接抛異常
(2).
captureCallStackTrace();
字面意思:捕獲調用堆棧跟蹤,我們通過源碼發現裡面涉及到了
retryAndFollowUpInterceptor
(3).
eventListener
回調
CallStart()
(4).
client.dispatcher().enqueue(new AsyncCall(responseCallback));
調用了
Dispatcher.enqueue()
并傳入了一個
new AsyncCall(responseCallback)
執行個體,點選AsyncCall檢視:
AsyncCall 是RealCall的内部類!
final class AsyncCall extends NamedRunnable {
private final Callback 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 void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("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 {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
}
複制
AsyncCall
繼承了
NamedRunnable
,我們看下
NamedRunnable
是什麼:
public abstract class NamedRunnable implements Runnable {
protected final String name;
public NamedRunnable(String format, Object... args) {
this.name = Util.format(format, args);
}
@Override public final void run() {
String oldName = Thread.currentThread().getName();
Thread.currentThread().setName(name);
try {
execute();
} finally {
Thread.currentThread().setName(oldName);
}
}
protected abstract void execute();
}
複制
原來
NamedRunnable
實作了
Runnable
接口 是個線程類,在
run()
中 添加了抽象的
execute();
方法,看到這裡 我們應該有一個反應,那就是AsyncCall中具體的execute()應該在子線程執行
我們繼續分析,
client.dispatcher().enqueue(new AsyncCall(responseCallback));
點選進入enqueue():
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
複制
-
正在運作的異步請求的隊列runningAsyncCalls
-
最大的請求數 64maxRequests
-
host最大請求數 5 (可以通過Get與Set方式自定義設定)maxRequestsPerHost
如果正在運作的異步請求的隊列大小低于64并且 正在請求的host數量低于5,就會執行(滿足條件)
runningAsyncCalls.add(call);
executorService().execute(call);
複制
這裡把
AsyncCall
執行個體添加到
runningAsyncCalls
中。
ExecutorService
表示線程池 繼續看
executorService()
:
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
複制
其實就是生成了executorService 執行個體,這就明白了,
AsyncCall
執行個體放入線程池中執行了!
如果不滿足上面的請求數等條件:
readyAsyncCalls.add(call);
複制
就會被添加到一個等待就緒的異步請求隊列中,目的是什麼呢??? 當然是等待時機再次添加到runningAsyncCalls中并放入線程池中執行,這塊邏輯在
AsyncCall
類中的
execute()
至于原因我們繼續往下看!
剛才我們說了,如果條件滿足,
AsyncCall
執行個體就會線上程池中執行(.start),那我們直接去看run()中的
execute()
:
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("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 {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
複制
上面代碼中得知, 首先通過層層攔截器鍊處理生成了
response
;然後通過一系列的判斷,
responseCallback
進行
onResponse
與
onFailure
回調,最後調用的
Dispatcher.finifshed()
這裡需要注意的是 這裡的
Dispatcher.finifshed(this)
與同步中的
Dispatcher.finifshed(this)
不一樣 參數不同。
/** Used by {@code AsyncCall#run} to signal completion. */
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
複制
我們繼續看具體的finifshed()方法:
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if (promoteCalls) promoteCalls();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
複制
線上程同步的情況下 執行了
promoteCalls();
:
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
複制
經過一系列的判斷, 對等待就緒的異步隊列進行周遊,生成對應的
AsyncCall
執行個體,并添加到runningAsyncCalls中,最後放入到線程池中執行! 這裡就是我們上面說到的等待就緒的異步隊列如何與runningAsyncCalls對接的邏輯。
總結
同步請求流程:
- 生成
執行個體realcallcall
-
中的Dispatcher.executed()
添加realcall到此隊列中runningSyncCalls
- 通過
對request層層攔截,生成ResponsegetResponseWithInterceptorChain()
- 通過
,把call執行個體從隊列中移除,傳回最終的responseDispatcher.finished()
異步請求流程:
- 生成一個
執行個體(實作了Runnable)AsyncCall(responseCallback)
-
執行個體放入了AsyncCall
中,并判斷Dispatcher.enqueue()
(最大請求數)maxRequests
(最大host請求數)是否滿足條件,如果滿足就把maxRequestsPerHost
添加到AsyncCall
中,并放入線程池中執行;如果條件不滿足,就添加到等待就緒的異步隊列,當那些滿足的條件的執行時 ,在runningAsyncCalls
中的Dispatcher.finifshed(this)
方法中 對等待就緒的異步隊列進行周遊,生成對應的promoteCalls();
執行個體,并添加到AsyncCall
中,最後放入到線程池中執行,一直到所有請求都結束。runningAsyncCalls
至此OKhttp整體流程就分析完了, 下一篇會分塊去分析,希望對大家有所幫助...