[Android]Volley源码分析(四)请求队列

 [Android]Volley源码分析(一)概述中,我们看到了Volley通过调研RequestQueue的start()方法启动了一个请求队列,下面我们通过代码看看具体是如何实现的:

    /**
     * Starts the dispatchers in this queue.
     */
    public void start() {
	    //首先取消当前所有运行的请求分发器dispatcher
        stop(); 
        // 创建一个缓存分发器并启动
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();

        // 创建一定数量的网络分发器并启动,默认大小是4
		// 其实这里就是实现了一个简单的线程池的功能
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                    mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }

通过代码我们发现请求队列启动时,启动了一个缓存分发器(Dispatcher)和4个网络分发器(Dispatcher)。这些分发器(Dispatcher)每个都维护了一个阻塞消息队列(BlockingQueue),阻塞消息队列(BlockingQueue)是为了实现“生产者-消费者”这种模型而设计的队列:当有消息加入队列时,则会一次取出消息执行,而当队列里没有消息时,则会一直等待。在androidsdk中阻塞消息队列(BlockingQueue)有三种实现方式:LinkedBlockingQueue,ArrayBlockingQueue和PriorityBlockingQueue。Volley采用的是PriorityBlockingQueue,这是一种基于消息优先级的高低来执行队列里消息的队列,具体可以参考http://ifeve.com/concurrent-collections-4/

下面我们看看如何添加一个请求(Request)到消息队列:

 /**
     * Adds a Request to the dispatch queue.
     * @param request The request to service
     * @return The passed-in request
     */
    public <T> Request<T> add(Request<T> 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 (!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)) {
                
				//已有请求发送,排队等待(在已有请求发送结束后会加等待队列里的请求发送到缓存队列,详看finish(Request<?> request)
                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 {
               
				//如果该请求尚未发送则加入缓存队列
                mWaitingRequests.put(cacheKey, null);
                mCacheQueue.add(request);
            }
            return request;
        }
    }

通过代码可以发现,如果使用缓存,则先将请求放入缓存队列,否则直接加入网络请求队列。

最后来看看如何取消特定tag的请求,这个设计有点意思:

 /**
     * A simple predicate or filter interface for Requests, for use by
     * 定义一个过滤请求的接口
     */
    public interface RequestFilter {
        public boolean apply(Request<?> request);
    }

    /**
     * 取消所有符合接口过滤条件的请求
     */
    public void cancelAll(RequestFilter filter) {
        synchronized (mCurrentRequests) {
            for (Request<?> request : mCurrentRequests) {
                if (filter.apply(request)) {
                    request.cancel();
                }
            }
        }
    }

    /**
     * 取消所有符合特定tag的请求
     */
    public void cancelAll(final Object tag) {
        if (tag == null) {
            throw new IllegalArgumentException("Cannot cancelAll with a null tag");
        }
        cancelAll(new RequestFilter() {
            @Override
            public boolean apply(Request<?> request) {
                return request.getTag() == tag;
            }
        });
    }

首先设计一个过滤接口,然后将该接口作为过滤条件,取消特定的请求。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值