Volley源码解析 --- CacheDispatcher缓存线程(2)

CacheDispatcher

缓存线程默认只有一个线程,负责从缓存队列取出请求并执行
下面是其执行的主要源码:

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.
                    mNetworkQueue.put(request);
                    continue;
                }

                // If it is completely expired, just send it to the network.
                if (entry.isExpired()) {
                    request.addMarker("cache-hit-expired");
                    request.setCacheEntry(entry);
                    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");

                //请求是否需要刷新
                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;

                    // 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) {
                                // Not much we can do about this.
                            }
                        }
                    });
                }

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

按照上面顺序执行过程,可总结为:

  1. mCacheQueue.take()从阻塞缓存队列取出一个请求
  2. 如果请求已经取消就finish结束这个请求
  3. 根据请求的url查看文件换成中是否已经有这个缓存,没有缓存或者缓存已经过期都需要重新请求,所以将其加入网络请求队列
  4. 有缓存,则取出缓存数据构建一个Response对象,这里再次判断这个缓存有没有立即刷新的标识,有或者没有这个标识都需要将response回调给它的请求者,只是有这个标识还要在请求一次数据,即把Request请求加入网络对象中去

关于缓存如何去使用?

通常我们使用Volley并没有过多的去设置我们的请求使用缓存,如果需要使用,在请求Request的时候要先去设置缓存标识:

public final Request setShouldCache(boolean shouldCache) {
        mShouldCache = shouldCache;
        return this;
    }

最后这个缓存还需要由我们自己去存储,Volley所有的请求完成后都会回调这个parseNetworkResponse,如果我们自定义请求,,我们重写这个方法,在这个方法中存储好我们的数据即可,可以参考下面StringRequest的方法去保存:

 @Override
    protected Response parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }

小知识点

后台线程尽量为其设置一个优先级,以便线程调度器更好的调度线程

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

子线程退出方法

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

   @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 {
               .....

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

最后,由于CacheDispatcher执行比较简单,再次就不画流程图了

你可能感兴趣的:(Volley源码解析 --- CacheDispatcher缓存线程(2))