Volley源码阅读之请求队列(RequestQueue)工作原理

本文详细介绍了Volley框架中的RequestQueue组件,包括其内部结构、请求处理流程以及关键方法的实现原理。阐述了缓存与网络请求的分发机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请求队列RequestQueue是一个拥有分发器线程池的请求分发队列。把一个请求入队,那么可能会执行缓存分发器队列里面的请求,也可能直接执行网络分发器队列里面的请求。如果请求有存在在缓存分发器队列中,那么根据特定条件来执行(到底如何执行请求的,请看上一篇博客Volley源码阅读之缓存分发器(CacheDispatcher)工作原理)。
下面,我们先来看RequestQueue的几个成员变量以及作用:

/**请求的集结区(有一份副本在执行)*/
 private final Map<String, Queue<Request<?>>> mWaitingRequests =
            new HashMap<String, Queue<Request<?>>>();
    /**所有正在被当前请求队列处理的请求的集合,任何一个在队列中等待或者正在被这个队列处理的请求都会加入到此集结区*/
    private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
    /** 缓存级别的请求队列*/
    private final PriorityBlockingQueue<Request<?>> mCacheQueue =
        new PriorityBlockingQueue<Request<?>>();
    /** 直接请求网络的请求的队列*/
    private final PriorityBlockingQueue<Request<?>> mNetworkQueue =
        new PriorityBlockingQueue<Request<?>>();
    /** 网络分发器池的默认的大小*/
    private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;
    /** 回调和存储响应*/
    private final Cache mCache;
    /** 执行网络分发器发来的请求*/
    private final Network mNetwork;
    /**响应传递 */
    private final ResponseDelivery mDelivery;
    /** 网络分发器 */
    private NetworkDispatcher[] mDispatchers;
    /** 缓存分发器 */
    private CacheDispatcher mCacheDispatcher;
    ......

创建出RequestQueue的对象来要调用start方法才能让请求队列工作。start方法是启动网络分发器后者缓存分发器的方法。现在我们先来看看请求队列RequestQueue的start()方法。

public void start() {
        stop();  //关闭所有正在执行的分发器 
        // 创建缓存分发器并启动它
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();

        // 根据分发池大小来创建网络分发器池,池的大小是在创建RequestQueue的时候就指定的了
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }

由以上源码的分析可以知道,RequestQueue开始分发请求的时候,首先会从缓存中获取数据,如果没有想要的数据,那么就会从网络中获取。从网络中获取使用了池。
请求队列RequestQueue还有一个重要的方法,就是add方法:

public <T> Request<T> add(Request<T> request) {
        // 加入当前请求集合
        request.setRequestQueue(this);
        synchronized (mCurrentRequests) {
            mCurrentRequests.add(request);
        }

        // 根据添加顺序来执行请求
        request.setSequence(getSequenceNumber());
        request.addMarker("add-to-queue");

        // 如果请求不需要缓存,直接把请求添加进网络分发器
        if (!request.shouldCache()) {
            mNetworkQueue.add(request);
            return request;
        }

        // 如果已经有相同的缓存key(请求的url)的请求,把请求加入集结区
        synchronized (mWaitingRequests) {
            String cacheKey = request.getCacheKey();
            if (mWaitingRequests.containsKey(cacheKey)) {
                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 {
              //null值代表开始有一个cacheKey请求在执行中
                mWaitingRequests.put(cacheKey, null);
                //添加缓存
                mCacheQueue.add(request);
            }
            return request;
        }
    }

可以知道,add方法添加请求的时候,如果请求不需要缓存那么直接交给网络分发器处理就可以了。如果需要缓存,首先判断集结区是否已经有这个请求存在。如果存在,则重设这个请求的值(Map结构中相同的key的value值会覆盖,mWaitingRequests是HashMap集合。),如果不存在那么就往缓存分发器添加这个请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值