Volley缓存-原理介绍
来源:互联网 发布:菲律宾网络诈骗 编辑:程序博客网 时间:2024/06/10 21:26
本文将从以下方面介绍Volley的缓存机制
- 使用缓带来哪些优势
- Volley的缓存原理
- Volley对服务端header解析
- Volley缓存过期判断
使用缓带来哪些优势:
- 速度:已缓存的资源加载的更快;
- 减少服务器负载:不用每次都和服务器进行交互;
- 较少网络流量:对于已缓存且在有效期内的数据将不会再次向服务器请求,如果已过期,只需要判断返回的数据是否发生变化,没有变化返回304,告诉客户端可以使用以前的缓存数据,否则返回新的数据;
- 离线浏览:用户可以在离线时使用;
Volley缓存原理
Volley的缓存原理和浏览器的缓存原理基本一致,基于HTTP协议,通过HTTP协议Header中的Cache-Control(或Expires)和Last-Modified(或Etag)等字段来控制缓存,再使用DiskBasedCache类将数据存储在本地;,下面对Header里面的一些字段进行说明, 服务端:Cache-Control、Expires、max-age、Last-Modified、ETag、stale-while-revalidate、must-revalidate、proxy-revalidate、no-cache、no-store;客户端:If-Modified-Since、If-None-Match;
服务端:
- Cache-Control:控制是否进行缓存,Http1.1后才出现,可添加的配置信息如下:
- no-cache或no-store,示列:Cache-Control:no-store或Cache-Control:no-cache表示不缓存数据
- max-age:缓存有效期(单位秒);示列Cache-Control:max-age=60表示基于当前时间60秒后缓存数据过期
- stale-while-revalidate:异步缓存机制(单位秒),当请求一个即将过期的文件时,会将本地的过期数据返回给用户,然后在异步请求数据,与must-revalidate或proxy-revalidate配套使用;示列:Cache-Control:stale-while-revalidate=1
- must-revalidate或proxy-revalidate:表示是否启用stale-while-revalidate字段,有了该字段后stale-while-revalidate才会生效;示列:Cache-Control:stale-while-revalidate=1;must-revalidate
- Expires:表示在该指定日期前缓存数据有效;示列:Expires:1451273426630
- Last-Modified:最后一次修改时间,精确到秒;可表示某个文件或者某个请求返回数据的最后修改时间,与If-Modified-Since配套使用,服务端通过取If-Modified-Since值与需要返回的Last-Modified值进行对比判断是否返回304;示列:Last-Modified:1451273426630
ETag:表示某个请求或者某个文件的标记,如某个文件或者某个请求返回数据的md5值、hashcode值等,与If-None-Match配套使用,服务端通过取If-None-Match值与需要返回的ETag值进行对比判断是否返回304;示列:ETag:ee4f36eca94844eaebfcc2633f1a8de8
客户端:
If-Modified-Since:最后一次修改时间;值取服务端Last-Modified值,在客户端header中设置该字段,服务端取值后与需要返回的Last-Modified值进行对比判断是否返回304
If-None-Match:缓存标识:值取服务端ETag值,在客户端的header中设置该字段,服务端取值后与需要返回的ETag值进行对比判断是否返回304
Volley在BasicNetwork的addCacheHeaders方法中对If-Modified-Since和If-None-Match进行设置,代码如下:
private void addCacheHeaders(Map<String, String> headers, Cache.Entry entry) { // If there's no cache entry, we're done. if (entry == null) { return; } if (entry.etag != null) { headers.put("If-None-Match", entry.etag); } if (entry.lastModified > 0) { Date refTime = new Date(entry.lastModified); headers.put("If-Modified-Since", DateUtils.formatDate(refTime)); } }
Volley对服务端header解析
Volly中对服务返回header信息的解析在HttpHeaderParser的parseCacheHeaders方法中,下面展现部分代码:
.........省略部分代码............ 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.startsWith("stale-while-revalidate=")) { try { staleWhileRevalidate = Long.parseLong(token.substring(23)); } catch (Exception e) { } } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) { mustRevalidate = true; } } } headerValue = headers.get("Expires"); if (headerValue != null) { serverExpires = parseDateAsEpoch(headerValue); } headerValue = headers.get("Last-Modified"); if (headerValue != null) { lastModified = parseDateAsEpoch(headerValue); } 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; finalExpire = mustRevalidate ? softExpire : softExpire + staleWhileRevalidate * 1000; } else if (serverDate > 0 && serverExpires >= serverDate) { // Default semantic for Expire header in HTTP specification is softExpire. softExpire = now + (serverExpires - serverDate); finalExpire = softExpire; }.........省略部分代码............
从以上代码中可以看出Cache-Control的优先级要高于 Expires
Volley缓存过期判断
Volley的缓存逻辑处理在CacheDispatcher类的run方法中;
- 通过Cache.Entry entry = mCache.get(request.getCacheKey());取出缓存信息,如果不存在缓存信息,则将请求放入mNetworkQueue
- 通过 Cache.Entry 的isExpired()方法判断缓存是否过期;isExpired()方法代码如下:
/** True if the entry is expired. */ public boolean isExpired() { return this.ttl < System.currentTimeMillis(); }
这里的ttl时候为header解析时的finalExpire时间,如果过期,则将请求放入mNetworkQueue;finalExpire取值如下:
// Cache-Control takes precedence over an Expires header, even if both exist and Expires // is more restrictive. if (hasCacheControl) { softExpire = now + maxAge * 1000; finalExpire = mustRevalidate ? softExpire : softExpire + staleWhileRevalidate * 1000; } else if (serverDate > 0 && serverExpires >= serverDate) { // Default semantic for Expire header in HTTP specification is softExpire. softExpire = now + (serverExpires - serverDate); finalExpire = softExpire; }
可以看出finalExpire>=softExpire ,与stale-while-revalidate和must-revalidate或proxy-revalidate的设置有关。
3.通过Cache.Entry的refreshNeeded()方法判断是否需要刷新
/** True if a refresh is needed from the original data source. */ public boolean refreshNeeded() { return this.softTtl < System.currentTimeMillis(); }
这里的sotfTtl时间为softExpire,该方法的用途如下:
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. } } }); }
这段代码表示如果不需要刷新,这将数据直接返回缓存数据,否则,返回缓存数据的同时异步请求新的数据。
- Volley缓存-原理介绍
- Volley缓存原理
- HTTP缓存原理介绍
- HTTP 缓存原理介绍
- HTTP缓存原理介绍
- 通过Volley我们能学到什么?(3) — 缓存原理
- Volley+瀑布流+缓存
- Volley 使用的缓存
- Volley Cache缓存机制
- Volley的缓存机制
- Volley更改缓存目录
- Volley中的默认缓存
- Volley缓存策略
- Volley的缓存策略
- Volley缓存分析
- Volley缓存机制
- Volley HTTP 缓存机制
- Part1:Volley磁盘缓存
- js判断复选框的数量
- OA系统的左侧菜单栏的菜单项的处理
- mac上mysql root密码忘记或权限错误的解决办法
- Android学习路线指南
- hdu1879 最小生成树模板 peim和kruskal
- Volley缓存-原理介绍
- Javascript:谈谈JS的全局变量跟局部变量
- Project Euler Problem 4
- 设计原则之迪米特法则
- Correspondence analysis application
- iOS 学习(深拷贝 浅拷贝)
- 搜索字符串strstr()函数
- Fresco通过后处理器(Postprocessor)生成仿skype字母和背景色的头像
- setLastFrameCallFunc接口不能使用解决方案