Android volley 解析(四)之缓存篇

这是 volley 的第四篇 blog 了,写完这篇,volley 的大部分用法也都算写了一遍,所以暂时不会写 volley 的文章了,如果想看我前面写的文章,可以点这里 Android volley 解析(三)之文件上传篇

为什么要用缓存

我们知道,当客户端在请求网络数据的时候,是需要消耗流量的,特别是对于移动端用户来说,对于流量的控制要求很高。所以在做网络请求的时候,如果对数据更新要求不是特别高,往往都会用到缓存机制,一方面能减少对服务端的请求,控制流量;另一方面,当客户端在没有网络的情况下也能看到上一次请求的数据,这样使用户体验更佳,如下图,微信朋友圈在没有网络的情况下,依然能看到朋友们的动态

volley 缓存的原理

看了我前面blog 的朋友一定还记得,我在讲 get 请求的时候,讲到了volley 的基本流程,首先启动的是缓存线程mCacheDispatcher来获取缓存; 那我们就从如何获取缓存开始分析; 1、初始化缓存

@Overridepublic 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) {…

2、获取缓存

while (true) {try {Request request = mCacheQueue.take();request.addMarker(“cache-queue-take”);// If the request has been canceled, don’t bother dispatching it….

这里有一个问题,缓存队列在什么时候添加缓存请求呢?我们回到最开始请求队列添加请求的地方

public Request add(Request 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();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;}}

代码不长,也很好理解,如果我们的请求没有设置了缓存,则请求添加到网络请求队列中,并直接返回了,不往下执行了,这时缓存队列中无法获取请求,所以这里我们知道了,想要用缓存则需要 在 Request 中把

(boolean shouldCache) {mShouldCache = shouldCache;}

设为 true,,当然,我们看mShouldCache 的默认值

/*** Whether or not responses to this request should be cached.*/private boolean mShouldCache = true;

volley默认启用缓存的。再往下看

// 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”);Log.i(“CacheDispatcher”, “没有缓存数据:” + request.getUrl());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);Log.i(“CacheDispatcher”, “缓存数据过期:” + request.getUrl());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.Log.i(“CacheDispatcher”, “获取缓存数据:” + request.getUrl());mDelivery.postResponse(request, response);} else {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() {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;}continue;}}人生如果错了方向,停止就是进步”。

Android volley 解析(四)之缓存篇

相关文章:

你感兴趣的文章:

标签云: