Volley Cache缓存机制
来源:互联网 发布:逝去的武林知乎 编辑:程序博客网 时间:2024/05/18 00:51
http://item.congci.com/item/volley-cache-huancun-jizhi
1.http缓存机制
要弄明白volley缓存机制,那么肯定是和浏览器的缓存机制有关了,简单来说volley整套框架要做的事都是模拟浏览器来进行一次次的http交互
1.1.概述
http缓存的是指当Web请求抵达缓存时, 如果本地有“已缓存的”副本,就可以从本地存储设备而不是从原始服务器中提取这个文档。
1.2.与缓存有关的头信息
1.2.1.request:
- Cache-Control: max-age=0 以秒为单位
- If-Modified-Since: Mon, 19 Nov 2012 08:38:01 GMT 缓存文件的最后修改时间。
- If-None-Match: "0693f67a67cc1:0" 缓存文件的Etag值
- Cache-Control: no-cache 不使用缓存
- Pragma: no-cache 不使用缓存
1.2.2.response:
- Cache-Control: public 响应被缓存,并且在多用户间共享
- Cache-Control: private 响应只能作为私有缓存,不能在用户之间共享
- Cache-Control:no-cache 提醒浏览器要从服务器提取文档进行验证
- Cache-Control:no-store 绝对禁止缓存(用于机密,敏感文件)
- Cache-Control: max-age=60 60秒之后缓存过期(相对时间)
- Date: Mon, 19 Nov 2012 08:39:00 GMT 当前response发送的时间
- Expires: Mon, 19 Nov 2012 08:40:01 GMT 缓存过期的时间(绝对时间)
- Last-Modified: Mon, 19 Nov 2012 08:38:01 GMT 服务器端文件的最后修改时间
- ETag: "20b1add7ec1cd1:0" 服务器端文件的Etag值
如果同时存在cache-control和Expires怎么办呢?
优先使用cache-control,如果没有cache-control才考虑Expires
2.Volley缓存机制
1.当你add进来一个request的时候,其会根据request.shouldCache(默认为true)进行分发决定是交给NetworkDispatcher还是CacheDispatcher处理
2.NetworkDispatcher通过Network请求数据, 如果有缓存的头信息,会一起发送给服务器
// Perform the network request. NetworkResponse networkResponse = mNetwork.performRequest(request);public NetworkResponse performRequest(Request<?> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while (true) { ..... ..... ..... addCacheHeaders(headers, request.getCacheEntry()); ..... ..... ..... } }
3.解析NetworkResponse
Response<?> response = request.parseNetworkResponse(networkResponse);
在这,得在自定义的request中调用很重要的一个静态方法
HttpHeaderParser.parseCacheHeaders(response)
这个方法主要是将NetworkResponse进行封装成一个Cache.Entry对象
public static Cache.Entry parseCacheHeaders(NetworkResponse response) { //当前系统时间 long now = System.currentTimeMillis(); Map<String, String> headers = response.headers; long serverDate = 0; long serverExpires = 0; long softExpire = 0; long maxAge = 0; boolean hasCacheControl = false; String serverEtag = null; String headerValue; headerValue = headers.get("Date"); if (headerValue != null) { //服务器时间 serverDate = parseDateAsEpoch(headerValue); } //获取Cache-Control信息 headerValue = headers.get("Cache-Control"); if (headerValue != null) { hasCacheControl = true; String[] tokens = headerValue.split(","); for (int i = 0; i < tokens.length; i++) { String token = tokens[i].trim(); if (token.equals("no-cache") || token.equals("no-store")) { //不缓存 return null; } else if (token.startsWith("max-age=")) { try { //缓存过期时间(相对时间) maxAge = Long.parseLong(token.substring(8)); } catch (Exception e) { } } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) { maxAge = 0; } } } headerValue = headers.get("Expires"); if (headerValue != null) { //过期时间(绝对时间) serverExpires = parseDateAsEpoch(headerValue); } //ETag serverEtag = headers.get("ETag"); // Cache-Control takes precedence over an Expires header, even if both exist and Expires // is more restrictive. if (hasCacheControl) { //软件过期时间 softExpire = now + maxAge * 1000; } else if (serverDate > 0 && serverExpires >= serverDate) { // Default semantic for Expire header in HTTP specification is softExpire. softExpire = now + (serverExpires - serverDate); } Cache.Entry entry = new Cache.Entry(); entry.data = response.data; entry.etag = serverEtag; entry.softTtl = softExpire; entry.ttl = entry.softTtl; entry.serverDate = serverDate; entry.responseHeaders = headers; return entry; }
4.在NetworkDispatcher中,再根据其shouldCache和是否有缓存实体来判断是否要进行缓存操作
if (request.shouldCache() && response.cacheEntry != null) { mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); }
5.CacheDispatcher的处理
当收到一个request之后,会先到Cache里面去取,看下是否有缓存,
当出现没有缓存 和 缓存过期的情况就直接丢给NetworkDispatcher来处理;
如果缓存没过期,直接拿到缓存实体丢给request的parseNetworkResponse方法这里调用就和NetworkDispatcher里面处理差不多了;
@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. 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; } continue; } } }
- Volley Cache缓存机制
- Volley的缓存机制
- Volley缓存机制
- Volley HTTP 缓存机制
- Volley Http缓存机制
- Cache-Control缓存机制
- Volley的cache之硬盘缓存--DiskBasedCache
- 从源码上看Volley的缓存机制,volley缓存
- Hibernate缓存机制----二级Cache
- Volley详解(四)——缓存(Cache)
- ZendFramework中使用Cache缓存机制
- thinkphp 中的cache缓存机制更是强大
- HTTP请求中的缓存(cache)机制
- 缓存机制Cache ARC算法(一)
- 缓存机制 Cache ARC算法(二)
- HTTP请求中的缓存(cache)机制
- HTTP请求中的缓存(cache)机制
- HTTP请求中的缓存(cache)机制
- MongoDB 数据库与 MySQL 操作
- tomcat启动一闪而过 相关问题总结
- android安全问题(二) 程序锁
- 在eclipse中怎么运行j2ee项目到tomcat服务器中
- python3 库
- Volley Cache缓存机制
- 程序员必须1小时内解决的5个编程问题
- android安全问题(三) 钓鱼程序
- 分别定义教师类和干部类 采用多重继承方式 第五章第九题
- stdarg.h编写可变参数函数
- Printf 的格式输出探索
- csu 1554: SG Value
- win7 拨号651
- W3C网页标准与优势