上一篇我分析了OkHttp采用同步請求的實現原理,這一篇我將繼續分析它的第二種請求方式——異步請求,由于這是基于上一篇文章的內容之上的,所以在看這篇文章之前請先瀏覽上一篇文章http://blog.csdn.net/kbqf24/article/details/56839535。
所謂異步,就是我們不需要坐著等待它出結果,當它有了結果后會回調相應的方法。
讓我們來看看OKHttp的異步請求是如何實現的:
public void enqueue(Callback responseCallback) { this.enqueue(responseCallback, false); }我們要傳一個Callback接口對象進去,
void enqueue(Callback responseCallback, boolean forWebSocket) { synchronized(this) { if(this.executed) { throw new IllegalStateException("Already Executed"); } this.executed = true; } this.client.getDispatcher().enqueue(new Call.AsyncCall(responseCallback, forWebSocket, null)); }首先還是要獲得一個分發器,這點跟同步請求是一模一樣的,接著往下看
synchronized void enqueue(AsyncCall call) { if(this.runningCalls.size() < this.maxRequests && this.runningCallsForHost(call) < this.maxRequestsPerHost) { this.runningCalls.add(call); this.getExecutorService().execute(call); } else { this.readyCalls.add(call); } }原來進行異步請求是有門檻限制的,它要求總的異步請求的數量小于maxRequests =64,并且對于一個主機來說最多同時發出5個請求,如果沒有滿足這個條件,那么就將這個call對象加入到readyCalls數組中以備日后使用,這個數組相當于是一個緩沖數組,如果滿足了這個條件,那么就將AsyncCall這個對象添加到runningCalls數組當中,并且使用線程池來執行這個任務,那么這個AsyncCall到底是什么了?它是Call的一個內部類并且實現了Runnable接口,那么走 this.getExecutorService().execute(call);這個方法當然就是要去執行call里面的run()方法啊,我們來看看這個方法:
public final void run() { String oldName = Thread.currentThread().getName(); Thread.currentThread().setName(this.name); try { this.execute(); } finally { Thread.currentThread().setName(oldName); } }這個方法會去執行execute(),并且會在執行期間給每個任務所在的線程取不同的名字。
PRotected void execute() { boolean signalledCallback = false; try { Response e = Call.this.getResponseWithInterceptorChain(this.forWebSocket); if(Call.this.canceled) { signalledCallback = true; this.responseCallback.onFailure(Call.this.originalRequest, new IOException("Canceled")); } else { signalledCallback = true; this.responseCallback.onResponse(e); } } catch (IOException var7) { if(signalledCallback) { Internal.logger.log(Level.INFO, "Callback failure for " + Call.this.toLoggableString(), var7); } else { Request request = Call.this.engine == null?Call.this.originalRequest:Call.this.engine.getRequest(); this.responseCallback.onFailure(request, var7); } } finally { Call.this.client.getDispatcher().finished(this); } }Response e = Call.this.getResponseWithInterceptorChain(this.forWebSocket);這個方法是不是也很熟悉啊,跟同步獲取數據的方法是一摸一樣的,一個方法在上一篇文章中詳細說明了的,這里就不再展開來說了,然后再判斷這個任務是否被cancel掉了,如果是,那么就會調用我們傳入的Callback接口對象的onFailure()方法,如果沒有被取消,那么就會回調該接口中的onResponse(response)方法。 那么異步請求的代碼我們也就分析完了,跟同步請求其實區別并不大,我們來分析一下他們的區別, 1. 同步:將Call對象之間放入分發器Dispatcher中 異步:將AsyncCall對象放入分發器Dispatcher中, 2. 同步方法不會自動給你開線程去調用getResponseWithInterceptorChain(this.forWebSocket)獲取數據,所以你必須自己開啟線程去執行。 異步方法OkHttp會使用內部的線程池中的線程去執行獲取數據(getResponseWithInterceptorChain(this.forWebSocket))的耗時操作,所以你可以在主線程中使用異步請求。 3. 同步方法拿到返回的結果后直接返回,而異步請求獲取到結果后并不直接返回,而是將結果作為參數回調接口的方法去使用的。
新聞熱點
疑難解答