前面咱們講了 Okhttp的基本用法 Okhttp3源碼解析(1)-OkHttpClient分析 Okhttp3源碼解析(2)-Request分析web
咱們首先看一下在哪用到了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()
去:websocket
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
:cookie
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增長[]運算符重載。socket
(5).咱們回到execute()
繼續往下分析,剩下的代碼咱們提取出三行代碼:
equesr result = getResponseWithInterceptorChain();
生成一個Response 實例eventListener.callFailed(this, e);
:eventListener的callFailed回調client.dispatcher().finished(this);
:dispatcher實例的finished方法不難看出,getResponseWithInterceptorChain()
必定是此方法中的核心,字面意思是獲取攔截器鏈的響應,這就明白了,就是經過攔截器鏈處理後返回Response
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
正在運行的異步請求的隊列maxRequests
最大的請求數 64maxRequestsPerHost
host最大請求數 5 (能夠經過Get與Set方式自定義設置)若是正在運行的異步請求的隊列大小低於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對接的邏輯。
call
實例realcallDispatcher.executed()
中的runningSyncCalls
添加realcall到此隊列中getResponseWithInterceptorChain()
對request層層攔截,生成ResponseDispatcher.finished()
,把call實例從隊列中移除,返回最終的responseAsyncCall(responseCallback)
實例(實現了Runnable)AsyncCall
實例放入了Dispatcher.enqueue()
中,並判斷maxRequests
(最大請求數)maxRequestsPerHost
(最大host請求數)是否知足條件,若是知足就把AsyncCall
添加到runningAsyncCalls
中,並放入線程池中執行;若是條件不知足,就添加到等待就緒的異步隊列,當那些知足的條件的執行時 ,在Dispatcher.finifshed(this)
中的promoteCalls();
方法中 對等待就緒的異步隊列進行遍歷,生成對應的AsyncCall
實例,並添加到runningAsyncCalls
中,最後放入到線程池中執行,一直到全部請求都結束。至此OKhttp總體流程就分析完了, 下一篇會分塊去分析,但願對你們有所幫助...
你們能夠關注個人微信公衆號:「秦子帥」一個有質量、有態度的公衆號!