当前位置: 首页 > 工具软件 > RequestQueue > 使用案例 >

Volley中RequestQueue对request的add优化处理

寇开畅
2023-12-01

前言

使用过Volley的开发者应该很清楚,对于一个request只需要将它加入对Queue中即可,使用也非常简单,也许没有注意它的细节,看了下面的这个对request添加优化处理后,我们将明白Volley框架在一些细节方面做得很好,这种做事的态度值得我们学习。

代码分析

下面从代码中分析Volley的add request的处理方式,首先要了解一个变量:

//重复请求的暂存区域,存储相同cachekey的request
   private final Map<String, Queue<Request<?>>> mWaitingRequests =
            new HashMap<String, Queue<Request<?>>>();

然后看RequestQueue的add方法:

    /**
     * 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 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();
            //暂存相同cacheKey的request
            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;
        }
    }

这里分析执行过程:
1,将request加入到mCurrentRequests 中
2,如果request为不需要缓存,那么直接放入网络请求的Queue中
3,如果request为可以缓存,那么根据request的cacheKey 进行判断是否存在于mWaitingRequests中,如果已经存在,则将request放入对应的queue中暂存起来,否则在mWaitingRequests中标记对应的cacheKey 的request;

在request的的执行过程中,最终会到ExecutorDelivery类中ResponseDeliveryRunnable的run()方法,执行mRequest.finish(“done”),从而到mRequestQueue.finish(this);这里我们看RequestQueue的finish()方法怎么处理的:

    /**
     * Called from {@link Request#finish(String)}, indicating that processing of the given request
     * has finished.
     *
     */
    <T> void finish(Request<T> request) {
        // Remove from the set of requests currently being processed.
        synchronized (mCurrentRequests) {
            mCurrentRequests.remove(request);
        }
        synchronized (mFinishedListeners) {
          for (RequestFinishedListener<T> listener : mFinishedListeners) {
            listener.onRequestFinished(request);
          }
        }
    //核心操作
        if (request.shouldCache()) {
            synchronized (mWaitingRequests) {
                String cacheKey = request.getCacheKey();
                Queue<Request<?>> waitingRequests = mWaitingRequests.remove(cacheKey);
                if (waitingRequests != null) {
                    if (VolleyLog.DEBUG) {
                        VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.",
                                waitingRequests.size(), cacheKey);
                    }
                    // Process all queued up requests. They won't be considered as in flight, but
                    // that's not a problem as the cache has been primed by 'request'.
                    mCacheQueue.addAll(waitingRequests);
                }
            }
        }
    }

这里核心的操作为将mWaitingRequests中的request加入到mCacheQueue队列中。这样操作的好处就是针对多个cacheKey相同的request,等待第一个request执行完成后再执行剩下的request,这样就不用同时执行重复的网络操作,减少网络操作,提高响应速度;那么这种会在什么情况下发送呢?比如:网络较差的环境下,如果我们不停的刷新界面,导致多个相同的请求,这样势必会影响网络的处理能力,如果我们第一个请求执行完成后有了缓存数据,那么从缓存数据中取数据将要比网络中取数据快得多。当然同时执行多个cachekey相同的request的这种场景不多,但是Volley已经为我们考虑进去了,由此可以说明Volley在细节方面处理得很好。

总结:

平时我们在开发项目中,有时为了速度和效果忽略了某些细节,也许这些细节看似没多重要,但是要做好一款产品或者一个框架,细节的处理将决定我们的成败。

 类似资料: