7、volley 源码解析之缓存线程工作流程

文章摘要
1、volley 缓存线程运行流程
2、volley 实现分解步骤


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

简介:

volley有两个主要的民工,CacheDispatcher以及NetworkDispatcher,也是两个线程,管理并处理Request任务。

volley为了保证大批量的网络请求以及数据解析不会影响到主线程的用户交互,使用了很多线程以及线程封装技巧。包括这里的Cache。

在用户发起网络请求后,volley就将用户的请求,丢到了本文介绍的缓存进程,缓存线程如果没有能力处理,就丢给网络线程,并告诉它,老大需要数据结果,你赶紧去网络上去拿。老大只要结果,不要过程。

主线程很忙,ResponseDelivery负责传递消息,伴君如伴虎,为了防止打扰到主线程的工作,ResponseDelivery也可以有一个线程,在目前的源码里,ResponseDelivery充分利用Handler的MessageQueue优势,管理并小心的将结果传递给主线程。

那么,本文就来介绍下缓存线程的工作原理:

一、CacheDispatcher线程

  • 1、Volley中有三个线程,CacheDispatcher是其中的缓存线程。

  • 2、CacheDispatcher缓冲线程的目的是在缓冲池中,执行分流,将Request请求分发出去。
    线程循环运行,线程原料来自mCacheQueue,在主线程可通过RequestQueue.add方法将请求加入mCacheQueue。

  • 3、可以将工作流程简单归纳为以下几步:

    • 1、线程循环运行,线程原料来自mCacheQueue。
    • 2、优先从缓冲区获得数据,如果缓存区中存在数据,则直接返回数据给主线程。
    • 3、如果缓存区【没有命中数据】或者【缓存数据过期】,则将请求(Request)分发给NetworkDispatcher(网络线程),网络线程会重新同步数据。

附:流程图

  • Volley Cache Thread流程图.png

二、实现分析

1、线程循环运行,获得Request对象

while (true) {
  try {
    // Get a request from the cache triage queue, blocking until
    // at least one is available.
    //1、hlwang:CacheDispatcher原料来自mCacheQueue,第一步,获得Request
    final Request<?> request = mCacheQueue.take();
    request.addMarker("cache-queue-take");
    ... ...
  }
}

2、如果Request被用户取消了,则不再需要继续执行了

// If the request has been canceled, don't bother dispatching it.
//2、hlwang:如果request已取消,已经不需要继续了
if (request.isCanceled()) {
    request.finish("cache-discard-canceled");
    continue;
}

3、优先检查缓存区,如果数据没有命中(即:数据不存在),则交给Network线程去同步数据

// Attempt to retrieve this item from cache.
//3、hlwang:如果在缓存中,不存在数据,说明是新数据,则:交给mNetworkQueue去同步新数据。
Cache.Entry entry = mCache.get(request.getCacheKey());
if (entry == null) {
    request.addMarker("cache-miss");
    // Cache miss; send off to the network dispatcher.
    mNetworkQueue.put(request);
    continue;
}

4、如果缓存数据过期了,依旧交给Network线程去同步数据

// If it is completely expired, just send it to the network.
//4、hlwang:如果缓存过期,那么说明数据太旧了,交给mNetworkQueue去同步新数据。
if (entry.isExpired()) {
    request.addMarker("cache-hit-expired");
    request.setCacheEntry(entry);
    mNetworkQueue.put(request);
    continue;
}

5、缓存的数据被命中,则解析缓存数据,构建Response对象

// We have a cache hit; parse its data for delivery back to the request.
//5、wanghailu:我们命中了一条缓存数据(w找到了一个保质期内的缓存hl),解析数据并构建响应对象Response。
request.addMarker("cache-hit");
Response<?> response = request.parseNetworkResponse(
        new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");

6、如果缓存数据,不需要刷新,则将响应数据,通过Delivery回调给用户

if (!entry.refreshNeeded()) {
    // Completely unexpired cache hit. Just deliver the response.
    //6、如果entry数据不需要刷新,则使用mDelivery将响应传递出去
    mDelivery.postResponse(request, response);
} 

7、缓存的数据需要再次更新,那么现将缓存数据返回给用户,接着通过主线程发起同步数据请求

    // Soft-expired cache hit. We can deliver the cached response,
    // but we need to also send the request to the network for
    // refreshing.
    //7、虽然被缓存命中,但数据轻微过期。我们可以将缓存响应数据传递分发,
    //但我们同样需要将请求发送到mNetworkQueue去刷新、更新。
    request.addMarker("cache-hit-refresh-needed");
    request.setCacheEntry(entry);

    // Mark the response as intermediate.
    //7.1、更新response状态为  媒介
    response.intermediate = true;

    // Post the intermediate response back to the user and have
    // the delivery then forward the request along to the network.
    //7.2、主线程分发
    mDelivery.postResponse(request, response, new Runnable() {
        @Override
        public void run() {
            try {
                mNetworkQueue.put(request);
            } catch (InterruptedException e) {
                // Not much we can do about this.
            }
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容