Volley的RequestQueue用来缓存请求处理器CacheDispatch和网络请求处理器NetworkDispatch来处理Request的。当我们调用RequestQueue.start()是,两个处理器开始运行起来,等待Request的到来。

       

 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();
        }
    }

  Volley先读缓存然后,没有cache hit的话再从网络上获取,所以先启动CacheDispatcher,然后启动NetworkDispatcher。不过在启动处理器前先调用stop()函数清除掉以前RequestQueue里的过期的Dispatcher(Dispatcher都是继承Thread)。以防影响性能。Volley启动一个CacheDispatcher和4个NetworkDispatcher,之所以这样设计,个人人为是主要考虑到网络图片的下载,所以利用多个NetworkDispatcher来处理网络请求。然后看一下stop()函数。

   

   public void stop() {
        if (mCacheDispatcher != null) {
            mCacheDispatcher.quit();
        }
        for (int i = 0; i < mDispatchers.length; i++) {
            if (mDispatchers[i] != null) {
                mDispatchers[i].quit();
            }
        }
    }

   调用Dispatcher的quit()函数来结束线程。以NetworkDispatcher.quit()为例:

 public void quit() {
        mQuit = true;
        interrupt();
    }

  函数将mQuit变量置为true。为什么要这样做,因为在networkdispatcher线程中的中断异常处理中,判断mQuit的值,如果真,则退出循环,结束线程。否则continue,继续从Queue中去取Request处理。

 try {
                // Take a request from the queue.
                request = mQueue.take();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
                continue;
            }

  接下来,看下RequestQueue的add函数。

   

 public Request add(Request request) {
        // Tag the request as belonging to this queue and add it to the set of current requests.
        request.setRequestQueue(this);
        synchronized (mCurrentRequests) {
            mCurrentRequests.add(request);
        }

        // Process requests in the order they are added.
        request.setSequence(getSequenceNumber());
        request.addMarker("add-to-queue");

        // If the request is uncacheable, skip the cache queue and go straight to the network.
        if (!request.shouldCache()) {
            mNetworkQueue.add(request);
            return request;
        }

        // Insert request into stage if there's already a request with the same cache key in flight.
        synchronized (mWaitingRequests) {
            String cacheKey = request.getCacheKey();
            if (mWaitingRequests.containsKey(cacheKey)) {
                // There is already a request in flight. Queue up.
                Queue<Request> stagedRequests = mWaitingRequests.get(cacheKey);
                if (stagedRequests == null) {
                    stagedRequests = new LinkedList<Request>();
                }
                stagedRequests.add(request);
                mWaitingRequests.put(cacheKey, stagedRequests);
                if (VolleyLog.DEBUG) {
                    VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
                }
            } else {
                // Insert 'null' queue for this cacheKey, indicating there is now a request in
                // flight.
                mWaitingRequests.put(cacheKey, null);
                mCacheQueue.add(request);
            }
            return request;
        }
    }

  首先将Request加入到mCurrentRequests中,因为存在多个线程竞争的问题,在这个代码块上进行了同步。然后request.setSequence().为当前Request分配一个序列号,为什么这样做,因为我们下面要将Request放到NetworkQueue中或者CacheQueue中,这两个队列都是PriorityBlockingQueue,里面的元素是根据自定义的权重来排序的。PriorityBlockingQueue里的元素须实现Comparable接口,来看下我们这里的Requeset的实现:

    

 @Override
    public int compareTo(Request<T> other) {
        Priority left = this.getPriority();
        Priority right = other.getPriority();

        // High-priority requests are "lesser" so they are sorted to the front.
        // Equal priorities are sorted by sequence number to provide FIFO ordering.
        return left == right ?
                this.mSequence - other.mSequence :
                right.ordinal() - left.ordinal();
    }

  Request的策略是现根据每个Request的Priority来判断,如果两个Request的Priority相同,那么载根据两个Request的Sequence来进行判断队列里的先后顺序。

     

1 public enum Priority {
2         LOW,
3         NORMAL,
4         HIGH,
5         IMMEDIATE
6     }
View Code

相关文章: