`
f303153041
  • 浏览: 45588 次
社区版块
存档分类
最新评论

Volley 核心源码解析(三)

 
阅读更多
Volley 的任务调度模型

接着上一节的 RequestQueue,在Volley 初始化 RequestQueue的时候 会执行 RequestQueue 的 start()方法,在start方法中 初始化了,缓存调度器和网络调度器。

   public void start() {
        stop();  // Make sure any currently running dispatchers are stopped.
        // Create the cache dispatcher and start it.
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();

        // Create network dispatchers (and corresponding threads) up to the pool size.
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }


看看NetworkDispatcher  和 CacheDispatcher 是什么东东?

NetworkDispatcher extends Thread

CacheDispatcher extends Thread


结果两个都是线程类。

再看看循环体中 往一个叫做mDispatchers[i] 的数组中赋值了若干 NetworkDispatcher,且每个NetworkDispatcher都在创建的时候 就启动了。

找到 mDispatchers的定义:
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;

mDispatchers = new NetworkDispatcher[threadPoolSize];

原来是个默认4个元素的 线程组。

看到这里我似乎想到了线程池的基本概念,没错 这就是个线程池。



看看具体的 NetworkDispatcher 是什么样的?

做过JAVA 开发的都知道 继承 thread 类一定要重写 run()方法

在NetworkDispatcher中run 方法如下:

方法太长  一段一段的来看哈

因为是要做线程池嘛,所以线程要一直工作,所以一进run方法 就是 while(true){}
了,

  Request<?> request = mQueue.take();

mQueue:mNetworkQueue

在 PriorityBlockingQueue 队列中 take 方法如下:
   public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        E result;
        try {
            while ( (result = dequeue()) == null)
                notEmpty.await();
        } finally {
            lock.unlock();
        }
        return result;
    }

意思就是加锁 -->取出一个请求->释放锁->原队列中请求减少一个

这样就保证了 使用 volley 发送请求的时候  能按照发送请求的顺序去执行。


接下来 从队列中取出请求之后,给请求设置备注,判断请求时否被取消,如果被取消就finish。

request.addMarker("network-queue-take");

                // If the request was cancelled already, do not perform the
                // network request.
                if (request.isCanceled()) {
                    request.finish("network-discard-cancelled");
                    continue;
                }



紧接着,执行该请求:
  // Perform the network request.
NetworkResponse networkResponse = mNetwork.performRequest(request);

后面就是对 networkResponse 的一些状态判断和解析。

Response<?> response = request.parseNetworkResponse(networkResponse);

在volley 中 解析NetworkResponse 的具体方法 交给 Request 的 子类去实现。如,ImageRequest,JsonRequest,StringRequest等

同时,缓存 这个已经执行的请求:
if (request.shouldCache() && response.cacheEntry != null) {
                    mCache.put(request.getCacheKey(), response.cacheEntry);
                    request.addMarker("network-cache-written");
                }


看到这里,我们可以得出一个结论,Volley 初始化 RequestQueue 的时候 创建了一个
默认4个大小的线程池,每个线程同步 的从PriorityBlockingQueue 类型的请求队列中拿出一个请求并执行。



接下来看看 CacheDispatcher 缓存任务调度:


    /** The queue of requests coming in for triage. */
    private final BlockingQueue<Request<?>> mCacheQueue;

    /** The queue of requests going out to the network. */
    private final BlockingQueue<Request<?>> mNetworkQueue;

与 NetworkDispatcher 不同的是 CacheDispatcher  不仅有缓存队列 还有请求队列,

同样是while (true) {  request = mCacheQueue.take();;  ...}

不停的从 mCacheQueue 拿出缓存过的请求:
// Attempt to retrieve this item from cache.
                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;
                }
这里看到 被缓存的请求时根据请求的cacheKey 从cache中取出,如果取出的缓存为空,直接把请求 放到 mNetworkQueue ,也就是说把请求交给 了 NetworkDispatcher去执行。

如果请求的缓存对象过期,同上:
  // If it is completely expired, just send it to the network.
                if (entry.isExpired()) {
                    request.addMarker("cache-hit-expired");
                    request.setCacheEntry(entry);
                    mNetworkQueue.put(request);
                    continue;
                }
这里我们看到一个关键性的代码:
Response<?> response = request.parseNetworkResponse(
                        new NetworkResponse(entry.data, entry.responseHeaders));


这是什么意思呢?

  Volley不仅缓存了请求本身,而且缓存了请求的响应结果,此时做的就是从缓存中取出响应的结果,这样就不用再发请求去服务器上了。

接下来,

if (!entry.refreshNeeded()) {
                    // Completely unexpired cache hit. Just deliver the response.
                   mDelivery.postResponse(request, response);
                } else {
                    // Soft-expired cache hit. We can deliver the cached response,
                    // but we need to also send the request to the network for
                    // refreshing.
                    request.addMarker("cache-hit-refresh-needed");
                    request.setCacheEntry(entry);

                    // Mark the response as intermediate.
                    response.intermediate = true;

                    // Post the intermediate response back to the user and have
                    // the delivery then forward the request along to the network.
                    final Request<?> finalRequest = request;
                    mDelivery.postResponse(request, response, new Runnable() {
                        @Override
                        public void run() {
                            try {
                                mNetworkQueue.put(finalRequest);
                            } catch (InterruptedException e) {
                                // Not much we can do about this.
                            }
                        }
                    });
                }

如果缓存数据不需要刷新,只需要用回掉接口返回值,反之,把请求放入mNetworkQueue,等待 NetworkDispatcher 执行。



至此,Volley 的 线程模型分析告一段落,我们看到了线程组 NetworkDispatcher[] 和 单线程 CacheDispatcher 通过 两个  BlockingQueue 巧妙地实现了网络请求任务的交替轮换。



下一节  Volley的缓存 http://f303153041.iteye.com/blog/2281360
















分享到:
评论

相关推荐

    Volley源码解析

    Volley源码解析是理解其工作原理、优化网络请求的关键,下面我们将深入探讨Volley的核心组件、工作流程以及关键算法。 首先,Volley的核心组件包括RequestQueue、Network、Cache和ResponseDelivery。RequestQueue是...

    volley源码和jar包

    在压缩包中的"Volley.jar"是Volley库的编译结果,可以直接导入到Android项目中使用,无需解析源码。使用jar包时,开发者可以直接调用Volley提供的API,如`RequestQueue.add(Request)`来添加请求,或者使用`...

    volley框架源码实例

    首先,Volley的核心特点包括: 1. **缓存机制**:Volley提供了内存和磁盘缓存策略,能够快速响应网络请求,减少对服务器的依赖,提高用户体验。 2. **线程管理**:Volley内部使用了线程池来处理网络请求,确保在...

    google官方最新volley源码

    5. **强大的转换能力**:Volley支持多种数据格式,如JSON、XML等,可以自动解析响应数据,无需额外的解析步骤。 6. **错误处理**:Volley提供了统一的错误处理机制,方便开发者捕获和处理网络请求过程中可能出现的...

    android volley源码

    在深入了解Volley的源码之前,我们先来概述一下Volley的基本概念和核心功能。 Volley的主要目标是简化Android应用中的网络请求处理,提供了一套高效的网络请求管理机制,包括异步处理、缓存策略、错误处理和性能...

    volley源码

    Volley的核心设计理念是优化UI线程的性能,减少网络延迟对用户界面的影响,以及通过缓存机制提高用户体验。下面我们将深入探讨Volley的源码,了解其工作原理和主要功能。 1. **网络请求模块**: - `Request`类是...

    Volley源码

    Volley的核心特性包括: 1. **缓存策略**: - Volley提供了基于内存和磁盘的两级缓存机制,能够快速响应网络请求,减少对服务器的压力。内存缓存用于存储最近访问的数据,磁盘缓存则用于长期存储,即使应用关闭也...

    Android Volley源码20160414版

    Volley 的核心优势在于其对网络请求的优化、内存管理以及线程调度策略。 1. **RequestQueue**:这是 Volley 的主要入口点,负责管理多个 CacheDispatcher 和 NetworkDispatcher 线程,处理请求队列。RequestQueue ...

    google volley源码和jar

    在Volley的源码中,可以看到许多关键类的设计,如Request类用于封装网络请求信息,ResponseListener接口用于处理响应数据,Parser类用于解析数据等。此外,Volley还提供了强大的错误处理机制,使得开发者可以方便地...

    可查看Volley源码

    Volley的核心理念是优化内存使用,减少网络请求的延迟,以及通过缓存机制提高用户体验。这个名为"可查看Volley源码"的压缩包文件,很显然是为了帮助开发者深入理解Volley的工作原理,从而更好地利用它进行应用开发。...

    Volley源码及文档

    Volley是Google推出的一款高效的网络请求库,专为Android平台设计。...通过深入理解Volley的源码,开发者可以更好地利用其特性,提升应用的网络性能。提供的文档将帮助你理解和应用这些知识点,解决实际开发中的问题。

    Volley.jar及源码

    - **数据解析**:Volley内置了对JSON和String的解析支持,简化了数据处理流程。 - **错误处理**:Volley提供了统一的错误处理机制,方便开发者捕获和处理网络异常。 **2. Volley的使用步骤** - **添加依赖**:...

    volley和okhttp的jar包含volley源码

    - 数据解析:Volley支持多种数据格式,如JSON、XML,可以直接转换为Java对象。 - 取消请求:可以轻松取消不再需要的请求,避免资源浪费。 2. OkHttp是Square公司开发的一个高效的HTTP客户端,其设计理念是减少...

    Volley框架源码

    Volley框架的源码分析可以帮助开发者深入理解其工作原理,从而更好地优化网络请求性能,例如调整缓存策略、定制网络栈或实现自定义的解析器。通过对源码的学习,开发者还可以解决Volley在特定场景下可能遇到的问题,...

    android网络框架Volley-源码,范例,jar包

    其次,Volley支持多种网络请求类型,如GET、POST等,并且能够自动处理JSON和其他常见格式的数据解析,简化了开发过程。 在压缩包中的"android-volley-master"目录下,包含的是Volley的源码。通过对源码的学习,...

Global site tag (gtag.js) - Google Analytics