美文网首页
Volley源码学习7-CacheDispatcher类

Volley源码学习7-CacheDispatcher类

作者: 依然淳熙 | 来源:发表于2017-10-16 15:13 被阅读0次

所有的请求都是先经过CacheDispatcher类处理,然后如果需要进行进行处理才进入到NetworkDispatcher。原因是因为在RequestQueue的add()方法中是这样的:

      // 如果不能缓存,则将请求添加到网络请求队列中. 默认true
        if (!request.shouldCache()) {
            mNetworkQueue.add(request);
            return request;
        }
        mCacheQueue.add(request);

因为Request的shouldCache方法默认返回为True。所以请求不会加入到mNetworkQueue;然后来看一看CacheDispatcher是怎么处理请求的:

 @Override
    public void run() {
        if (DEBUG) VolleyLog.v("start new dispatcher");
        //线程优先级设置为最高级别
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

        // Make a blocking call to initialize the cache.
        mCache.initialize();

        while (true) {
            try {
                // Get a request from the cache triage queue, blocking until
                // at least one is available. 获取缓存队列中的一个请求
                final Request<?> request = mCacheQueue.take();
                request.addMarker("cache-queue-take");

                // If the request has been canceled, don't bother dispatching it. 如果请求取消了则将请求停止掉
                if (request.isCanceled()) {
                    request.finish("cache-discard-canceled");
                    continue;
                }

                // 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.  If false, we should continue issuing the request
                    if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                        mNetworkQueue.put(request);
                    }
                    continue;
                }

                // If it is completely expired, just send it to the network.
                //判断缓存响应是否过期
                Log.e("test","====="+entry.isExpired());
                if (entry.isExpired()) {
                    //过期
                    request.addMarker("cache-hit-expired");
                    //set cache
                    request.setCacheEntry(entry);
                    //If false, we should continue issuing the request
                    if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                        mNetworkQueue.put(request);
                    }
                    continue;
                }

                // We have a cache hit; parse its data for delivery back to the request.
                request.addMarker("cache-hit");

                Response<?> response = request.parseNetworkResponse(
                        new NetworkResponse(entry.data, entry.responseHeaders));
                request.addMarker("cache-hit-parsed");
                /** True if a refresh is needed from the original data source. */
                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;

                    if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                        // Post the intermediate response back to the user and have
                        // the delivery then forward the request along to the network.
                        mDelivery.postResponse(request, response, new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    mNetworkQueue.put(request);

                                } catch (InterruptedException e) {
                                    // Restore the interrupted status
                                    Thread.currentThread().interrupt();
                                }
                            }
                        });
                    } else {
                        // request has been added to list of waiting requests
                        // to receive the network response from the first request once it returns.

                        mDelivery.postResponse(request, response);
                    }
                }

            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    return;
                }
            }
        }
    }

经过各种情况的判断后如果需要重新请求就将请求加入mNetworkQueue,否则就通过mDelivery返回状态。其中maybeAddToWaitingRequests(request)方法如下:

/**
         * Staging area for requests that already have a duplicate request in flight.
         *
         * <ul>
         *     <li>containsKey(cacheKey) indicates that there is a request in flight for the given cache
         *          key.</li>
         *     <li>get(cacheKey) returns waiting requests for the given cache key. The in flight request
         *          is <em>not</em> contained in that list. Is null if no requests are staged.</li>
         * </ul>
         */
        private final Map<String, List<Request<?>>> mWaitingRequests = new HashMap<>();
/**
         * For cacheable requests, if a request for the same cache key is already in flight,
         * add it to a queue to wait for that in-flight request to finish.
         * @return whether the request was queued. If false, we should continue issuing the request
         * over the network. If true, we should put the request on hold to be processed when
         * the in-flight request finishes.   //如果这是真的,我们应该搁置请求处理动态的请求完成。
         */
        private synchronized boolean maybeAddToWaitingRequests(Request<?> request) {
            String cacheKey = request.getCacheKey(); //url
            // Insert request into stage if there's already a request with the same cache key
            // in flight.
            if (mWaitingRequests.containsKey(cacheKey)) {
                // There is already a request in flight. Queue up. 排队等候
                List<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
                if (stagedRequests == null) {
                    stagedRequests = new ArrayList<Request<?>>();
                }
                request.addMarker("waiting-for-response");
                stagedRequests.add(request);
                mWaitingRequests.put(cacheKey, stagedRequests);
                if (VolleyLog.DEBUG) {
                    VolleyLog.d("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
                }
                return true;
            } else {
                // Insert 'null' queue for this cacheKey, indicating there is now a request in
                // flight.
                mWaitingRequests.put(cacheKey, null);
                //listener
                request.setNetworkRequestCompleteListener(this);
                if (VolleyLog.DEBUG) {
                    VolleyLog.d("new request, sending to network %s", cacheKey);
                }
                return false;
            }
        }

其实就是维护CacheDispatcher的内部类WaitingRequestManager的mWaitingRequests等待队列。

相关文章

网友评论

      本文标题:Volley源码学习7-CacheDispatcher类

      本文链接:https://www.haomeiwen.com/subject/xuwkuxtx.html