国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

OkHttp的實(shí)現(xiàn)原理(二)之異步

2019-11-06 10:05:19
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

上一篇我分析了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)接口的方法去使用的。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 察隅县| 永兴县| 砚山县| 银川市| 广河县| 富宁县| 曲靖市| 沽源县| 乌拉特中旗| 石林| 临沧市| 上饶县| 延寿县| 交城县| 临沧市| 泽州县| 楚雄市| 永定县| 吐鲁番市| 九龙县| 泰安市| 红原县| 雷波县| 邻水| 乌拉特前旗| 城口县| 富宁县| 石门县| 鲁山县| 栾城县| 邢台市| 武威市| 汕尾市| 南昌县| 中宁县| 河北区| 勃利县| 大洼县| 哈尔滨市| 微山县| 金华市|