美文网首页Android知识
Volley源码解析 --- CacheDispatcher缓存

Volley源码解析 --- CacheDispatcher缓存

作者: jackzhoud | 来源:发表于2017-07-06 14:39 被阅读0次

    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<String> 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缓存

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