上一篇我分析了OkHttp采用同步請(qǐng)求的實(shí)現(xiàn)原理,這一篇我將繼續(xù)分析它的第二種請(qǐng)求方式——異步請(qǐng)求,由于這是基于上一篇文章的內(nèi)容之上的,所以在看這篇文章之前請(qǐng)先瀏覽上一篇文章http://blog.csdn.net/kbqf24/article/details/56839535。
所謂異步,就是我們不需要坐著等待它出結(jié)果,當(dāng)它有了結(jié)果后會(huì)回調(diào)相應(yīng)的方法。
讓我們來(lái)看看OKHttp的異步請(qǐng)求是如何實(shí)現(xiàn)的:
public void enqueue(Callback responseCallback) { this.enqueue(responseCallback, false); }我們要傳一個(gè)Callback接口對(duì)象進(jìn)去,
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)); }首先還是要獲得一個(gè)分發(fā)器,這點(diǎn)跟同步請(qǐng)求是一模一樣的,接著往下看
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); } }原來(lái)進(jìn)行異步請(qǐng)求是有門(mén)檻限制的,它要求總的異步請(qǐng)求的數(shù)量小于maxRequests =64,并且對(duì)于一個(gè)主機(jī)來(lái)說(shuō)最多同時(shí)發(fā)出5個(gè)請(qǐng)求,如果沒(méi)有滿足這個(gè)條件,那么就將這個(gè)call對(duì)象加入到readyCalls數(shù)組中以備日后使用,這個(gè)數(shù)組相當(dāng)于是一個(gè)緩沖數(shù)組,如果滿足了這個(gè)條件,那么就將AsyncCall這個(gè)對(duì)象添加到runningCalls數(shù)組當(dāng)中,并且使用線程池來(lái)執(zhí)行這個(gè)任務(wù),那么這個(gè)AsyncCall到底是什么了?它是Call的一個(gè)內(nèi)部類(lèi)并且實(shí)現(xiàn)了Runnable接口,那么走 this.getExecutorService().execute(call);這個(gè)方法當(dāng)然就是要去執(zhí)行call里面的run()方法啊,我們來(lái)看看這個(gè)方法:
public final void run() { String oldName = Thread.currentThread().getName(); Thread.currentThread().setName(this.name); try { this.execute(); } finally { Thread.currentThread().setName(oldName); } }這個(gè)方法會(huì)去執(zhí)行execute(),并且會(huì)在執(zhí)行期間給每個(gè)任務(wù)所在的線程取不同的名字。
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);這個(gè)方法是不是也很熟悉啊,跟同步獲取數(shù)據(jù)的方法是一摸一樣的,一個(gè)方法在上一篇文章中詳細(xì)說(shuō)明了的,這里就不再展開(kāi)來(lái)說(shuō)了,然后再判斷這個(gè)任務(wù)是否被cancel掉了,如果是,那么就會(huì)調(diào)用我們傳入的Callback接口對(duì)象的onFailure()方法,如果沒(méi)有被取消,那么就會(huì)回調(diào)該接口中的onResponse(response)方法。 那么異步請(qǐng)求的代碼我們也就分析完了,跟同步請(qǐng)求其實(shí)區(qū)別并不大,我們來(lái)分析一下他們的區(qū)別, 1. 同步:將Call對(duì)象之間放入分發(fā)器Dispatcher中 異步:將AsyncCall對(duì)象放入分發(fā)器Dispatcher中, 2. 同步方法不會(huì)自動(dòng)給你開(kāi)線程去調(diào)用getResponseWithInterceptorChain(this.forWebSocket)獲取數(shù)據(jù),所以你必須自己開(kāi)啟線程去執(zhí)行。 異步方法OkHttp會(huì)使用內(nèi)部的線程池中的線程去執(zhí)行獲取數(shù)據(jù)(getResponseWithInterceptorChain(this.forWebSocket))的耗時(shí)操作,所以你可以在主線程中使用異步請(qǐng)求。 3. 同步方法拿到返回的結(jié)果后直接返回,而異步請(qǐng)求獲取到結(jié)果后并不直接返回,而是將結(jié)果作為參數(shù)回調(diào)接口的方法去使用的。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注