9码耐、volley 源碼解析之消息分發(fā)工的工作流程

文章摘要
1窗市、volley 消息傳遞工 工作原理


附:獲取Volley源代碼
Demos案例源碼:https://github.com/HailouWang/DemosForApi

簡介:

volley有兩個主要的民工牛欢,CacheDispatcher以及NetworkDispatcher,也是兩個線程赃蛛,管理并處理Request任務(wù)恃锉。

volley為了保證大批量的網(wǎng)絡(luò)請求以及數(shù)據(jù)解析不會影響到主線程的用戶交互,使用了很多線程以及線程封裝技巧呕臂。包括這里的Cache破托。

在用戶發(fā)起網(wǎng)絡(luò)請求后,volley就將用戶的請求诵闭,丟到了本文介紹的緩存進(jìn)程炼团,緩存線程如果沒有能力處理,就丟給網(wǎng)絡(luò)線程疏尿,并告訴它瘟芝,老大需要數(shù)據(jù)結(jié)果,你趕緊去網(wǎng)絡(luò)上去拿褥琐。老大只要結(jié)果锌俱,不要過程。

主線程很忙敌呈,ResponseDelivery負(fù)責(zé)傳遞消息贸宏,伴君如伴虎,為了防止打擾到主線程的工作磕洪,ResponseDelivery也可以有一個線程吭练,在目前的源碼里,ResponseDelivery充分利用Handler的MessageQueue優(yōu)勢析显,管理并小心的將結(jié)果傳遞給主線程鲫咽。

那么,本文就來介紹下消息傳遞工(ResponseDelivery)的工作原理:

1谷异、傳遞工人(ResponseDelivery)初始化分尸。

在初始化RequestQueue工具類時,會初始化傳遞工歹嘹。傳遞工使用Handler來管理隊列箩绍,Handler的Looper來自主線程。

    /**
     * Creates the worker pool. Processing will not begin until {@link #start()} is called.
     *創(chuàng)建一個工作池尺上,非start方法調(diào)用前材蛛,不會開始執(zhí)行
     * @param cache A Cache to use for persisting responses to disk
     * 1、緩存者尖昏。將相應(yīng)數(shù)據(jù)持久化到硬盤
     * @param network A Network interface for performing HTTP requests
     * 2仰税、網(wǎng)絡(luò)處理者。處理HTTP請求的Network 接口
     * @param threadPoolSize Number of network dispatcher threads to create
     * 3抽诉、網(wǎng)絡(luò)請求分發(fā)者陨簇。默認(rèn)4個分發(fā)線程池
     * @param delivery A ResponseDelivery interface for posting responses and errors
     * 4、響應(yīng)傳遞者。傳遞響應(yīng)數(shù)據(jù)河绽,以及錯誤日志信息
     */
    public RequestQueue(Cache cache, Network network, int threadPoolSize,
            ResponseDelivery delivery) {
        mCache = cache;
        mNetwork = network;
        mDispatchers = new NetworkDispatcher[threadPoolSize];
        mDelivery = delivery;
    }

    /**
     * Creates the worker pool. Processing will not begin until {@link #start()} is called.
     *
     * @param cache A Cache to use for persisting responses to disk
     * @param network A Network interface for performing HTTP requests
     * @param threadPoolSize Number of network dispatcher threads to create
     */
    public RequestQueue(Cache cache, Network network, int threadPoolSize) {
        this(cache, network, threadPoolSize,
                new ExecutorDelivery(new Handler(Looper.getMainLooper())));
    }

在這里己单,原生提供了一種默認(rèn)的實現(xiàn):

new ExecutorDelivery(new Handler(Looper.getMainLooper()))

在這段代碼中,需要傳入一個Handler對象耙饰,對象中的Loop來自主線程纹笼,可以這么說,Handler工作在主線程中苟跪。

備注:我們也可以創(chuàng)建自己的傳遞工(ResponseDelivery)廷痘,原生提供的實現(xiàn)中,類圖如下:

2件已、傳遞工人(ResponseDelivery)接收回調(diào)任務(wù)笋额。

我們之前介紹過了,volley有兩個默默工作的勞工篷扩,它們就是CacheDispatcher以及NetworkDispatcher兄猩,勞工們在做完工作后,是沒有權(quán)利告訴主線程的鉴未,因為這是傳遞工人的工作枢冤。

NetworkDispatcher或者CacheDispatcher通過如下方式告訴ResponseDelivery,需要向主線程傳遞結(jié)果铜秆。

mDelivery.postResponse(request, response);

無論是Response還是Error淹真,所有的這些響應(yīng)都發(fā)給了ResponseDelivery中的線程池。

3连茧、傳遞工人對接收到的任務(wù)的處理

    public ExecutorDelivery(final Handler handler) {
        // Make an Executor that just wraps the handler.
        mResponsePoster = new Executor() {
            @Override
            public void execute(Runnable command) {
                handler.post(command);
            }
        };
    }
    @Override
    public void postResponse(Request<?> request, Response<?> response) {
        postResponse(request, response, null);
    }

    @Override
    public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
        request.markDelivered();
        request.addMarker("post-response");
        mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
    }

    @Override
    public void postError(Request<?> request, VolleyError error) {
        request.addMarker("post-error");
        Response<?> response = Response.error(error);
        mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null));
    }

線程池會將得到的消息趟咆,包裝一個Runnable,利用Handler發(fā)送給主線程梅屉。

// If this request has canceled, finish it and don't deliver.
//1、如果請求已經(jīng)取消鳞贷,則不必傳遞
if (mRequest.isCanceled()) {
    mRequest.finish("canceled-at-delivery");
    return;
}

// Deliver a normal response or error, depending.
if (mResponse.isSuccess()) {
    //2坯汤、如果Response沒有錯誤,則分發(fā)result
    mRequest.deliverResponse(mResponse.result);
} else {
    //3搀愧、如果Reponse有錯誤惰聂,則分發(fā)error
    mRequest.deliverError(mResponse.error);
}

// If this is an intermediate response, add a marker, otherwise we're done
// and the request can be finished.
//4、如果 響應(yīng)屬于媒介咱筛,標(biāo)記marker
if (mResponse.intermediate) {
    mRequest.addMarker("intermediate-response");
} else {
    mRequest.finish("done");
}

4搓幌、傳遞工人將消息回調(diào)給主線程。

通過3中可以看到迅箩,發(fā)往主線程的回調(diào)溉愁,是通過mRequest.deliverResponse來實現(xiàn)的。

/**
 * Subclasses must implement this to perform delivery of the parsed
 * response to their listeners.  The given response is guaranteed to
 * be non-null; responses that fail to parse are not delivered.
 * @param response The parsed response returned by
 * {@link #parseNetworkResponse(NetworkResponse)}
 */
abstract protected void deliverResponse(T response);

通過Request#deliverResponse饲趋,我們看到拐揭,這是一個Abstract方法撤蟆,不同的實現(xiàn),傳遞方式也不同堂污。這里介紹下原生的實現(xiàn):
StringRequest.java

@Override
protected void deliverResponse(String response) {
    mListener.onResponse(response);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末家肯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子盟猖,更是在濱河造成了極大的恐慌讨衣,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件式镐,死亡現(xiàn)場離奇詭異反镇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)碟案,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進(jìn)店門愿险,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人价说,你說我怎么就攤上這事辆亏。” “怎么了鳖目?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵扮叨,是天一觀的道長。 經(jīng)常有香客問我领迈,道長彻磁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任狸捅,我火速辦了婚禮衷蜓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尘喝。我一直安慰自己磁浇,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布朽褪。 她就那樣靜靜地躺著置吓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缔赠。 梳的紋絲不亂的頭發(fā)上衍锚,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天,我揣著相機(jī)與錄音嗤堰,去河邊找鬼戴质。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的置森。 我是一名探鬼主播斗埂,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼凫海!你這毒婦竟也來了呛凶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤行贪,失蹤者是張志新(化名)和其女友劉穎漾稀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體建瘫,經(jīng)...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡崭捍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了啰脚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片殷蛇。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖橄浓,靈堂內(nèi)的尸體忽然破棺而出粒梦,到底是詐尸還是另有隱情,我是刑警寧澤荸实,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布匀们,位于F島的核電站,受9級特大地震影響准给,放射性物質(zhì)發(fā)生泄漏泄朴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一露氮、第九天 我趴在偏房一處隱蔽的房頂上張望祖灰。 院中可真熱鬧,春花似錦畔规、人聲如沸夫植。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至延欠,卻和暖如春陌兑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背由捎。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工兔综, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓软驰,卻偏偏與公主長得像涧窒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锭亏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,442評論 2 359

推薦閱讀更多精彩內(nèi)容