有一个朋友在私信里问我,

1)Volley可以在SD卡中缓存图片,那可不可以在SD卡中缓存Json数据呢?

2)如果断网了,Volley是不是就不能用了,存在SD卡中的数据是不是就用不了了?

在Volley中,默认使用的缓存实现是 DiskBasedCache,在创建RequestQueue的时候,同时也会创建一个DiskBasedCache对象,如下:

[java] view plain copy  
  1. RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);

而缓存文件的位置就是由CacheDir提供的,它的值如下:

在前面的VolleyDemo中,我们加载了一些图片,也加载了一些json数据,那么我们现在就来看看在缓存中的数据,有没有缓存图片的数据,同时,有没有缓存json的数据。

Volley文件夹下面有以下几条数据:

在文件夹中,以"-993813455"开头的文件,其实就是图片文件的缓存,而以-165747开头的那个文件,其实就是我们从天气网站拿下来的json数据的缓存,我们可以打开看一下里面文件的信息,下面是缓存文件-993813455-446463727的内容:

[html] view plain copy  
  1. <       http://img.my.csdn.net/uploads/201403/03/1393854084_6138.jpg       "FhHq7DMn1v_jbLzbG84-iD_stqzT"榟?E  橮奓  橮奓            X-ViaN       1.1 gzck20:8107 (Cdn Cache Server V2.0), 1.1 dgck149:0 (Cdn Cache Server V2.0)       ETag       "FhHq7DMn1v_jbLzbG84-iD_stqzT"       X-Reqid       JAQAAFDYivywH2IT       X-Log       MC;IO:2       Content-Length       16713       Content-Transfer-Encoding       binary
  2. Connection
  3. keep-alive       Server        nginx/1.4.4
  4. Cache-Control       public, max-age=31536000       X-Whom       nb5       Date       Sat, 05 Apr 2014 16:01:19 GMT       Access-Control-Allow-Origin       *       Content-Disposition&       inline; filename="1393854084_6138.jpg"       X-Android-Received-Millis
  5. 1396713679439        Content-Type
  6. image/jpeg
  7. Accept-Ranges       bytes       X-Android-Sent-Millis
  8. 1396713678988??JFIF   d d  ?Ducky     <  ?慼ttp://ns.adobe.com/xap/1.0/ <?xpacket begin="锘? id="W5M0MpCehiHzreSzNTczkc9d"?>
  9. <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.1-c036 46.276720, Mon Feb 19 2007 22:13:43        ">
  10. <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  11. <rdf:Description rdf:about=""
  12. xmlns:dc="http://purl.org/dc/elements/1.1/"
  13. xmlns:xapRights="http://ns.adobe.com/xap/1.0/rights/"
  14. xapRights:Marked="Romain Guy"
  15. xapRights:WebStatement="Romain Guy">
  16. <dc:rights>
  17. <rdf:Alt>
  18. <rdf:li xml:lang="x-default">Romain Guy</rdf:li>
  19. </rdf:Alt>
  20. </dc:rights>
  21. </rdf:Description>
  22. </rdf:RDF>
  23. </x:xmpmeta>

我们可以看到文件的开头就是要展示的图片的url地址,再来看看Json数据的内容:

[html] view plain copy  
  1. 0       http://www.weather.com.cn/data/sk/101280101.html        (&?E                            Age       297       Transfer-Encoding       chunked       Date       Sat, 05 Apr 2014 16:31:37 GMT       X-Android-Received-Millis
  2. 1396715892761        Content-Type       text/html; charset=utf-8
  3. Connection       close       Server        Apache/2.2.0       X-Android-Sent-Millis
  4. 1396715892611{"weatherinfo":{"city":"骞垮窞","cityid":"101280101","temp":"18","WD":"瑗垮寳椋?,"WS":"1绾?,"SD":"92%","WSE":"1","time":"00:20","isRadar":"1","Radar":"JC_RADAR_AZ9200_JB"}}

不仅可以看到json数据的ulr地址,我们还可以看到下面具体的json数据,如“weatherinfo...”等信息。

从上面这两条数据,我们可以回答那位朋友的第一个问题,SD卡中不仅仅缓存图片,也是有缓存Json数据的。而事实上,通过网络获取来的数据其实都是字节流,Volley只是通过Response的Header信息来设置缓存记录的生命周期等,具体代码如下:

[java] view plain copy  
  1. public static Cache.Entry parseCacheHeaders(NetworkResponse response) {
  2. long now = System.currentTimeMillis();
  3. Map<String, String> headers = response.headers;
  4. long serverDate = 0;
  5. long serverExpires = 0;
  6. long softExpire = 0;
  7. long maxAge = 0;
  8. boolean hasCacheControl = false;
  9. String serverEtag = null;
  10. String headerValue;
  11. headerValue = headers.get("Date");
  12. if (headerValue != null) {
  13. serverDate = parseDateAsEpoch(headerValue);
  14. }
  15. headerValue = headers.get("Cache-Control");
  16. if (headerValue != null) {
  17. Log.v(Helper.TAG, "Has Cache-Control");
  18. hasCacheControl = true;
  19. String[] tokens = headerValue.split(",");
  20. for (int i = 0; i < tokens.length; i++) {
  21. String token = tokens[i].trim();
  22. if (token.equals("no-cache") || token.equals("no-store")) {
  23. return null;
  24. } else if (token.startsWith("max-age=")) {
  25. try {
  26. maxAge = Long.parseLong(token.substring(8));
  27. Log.v(Helper.TAG, "Max AGe = " + maxAge);
  28. } catch (Exception e) {
  29. }
  30. } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) {
  31. maxAge = 0;
  32. }
  33. }
  34. }
  35. headerValue = headers.get("Expires");
  36. if (headerValue != null) {
  37. serverExpires = parseDateAsEpoch(headerValue);
  38. }
  39. serverEtag = headers.get("ETag");
  40. // Cache-Control takes precedence over an Expires header, even if both exist and Expires
  41. // is more restrictive.
  42. if (hasCacheControl) {
  43. softExpire = now + maxAge * 1000;
  44. } else if (serverDate > 0 && serverExpires >= serverDate) {
  45. // Default semantic for Expire header in HTTP specification is softExpire.
  46. softExpire = now + (serverExpires - serverDate);
  47. }
  48. Log.v(Helper.TAG, "SoftExpire = " + softExpire);
  49. Cache.Entry entry = new Cache.Entry();
  50. entry.data = response.data;
  51. entry.etag = serverEtag;
  52. entry.softTtl = softExpire;
  53. entry.ttl = entry.softTtl;
  54. entry.serverDate = serverDate;
  55. entry.responseHeaders = headers;
  56. return entry;
  57. }

所以,其实不管数据是图片,还是Json数据,对于缓存来说,这并不重要。

那么我们来看看第二个问题,断网了,Volley是不是就不能用了?

通过前面Volley的框架图,我们知道,Volley首先会去缓存中找数据,如果找不到才会去网络中获取数据,所以如果缓存中有数据的话,它就不用去跟网络打交道了,那么跟断不断网其实也就关系不大了。

把手机设置成飞行模式,然后我们再去加载图片,我们可以看到在Log中的信息,如下:

[java] view plain copy  
  1. 04-06 11:44:43.671: D/Volley(6541): [1] MarkerLog.finish: (+0   ) [ 1] add-to-queue
  2. 04-06 11:44:43.671: D/Volley(6541): [1] MarkerLog.finish: (+434 ) [1059] cache-queue-take
  3. 04-06 11:44:43.671: D/Volley(6541): [1] MarkerLog.finish: (+17  ) [1059] cache-hit
  4. 04-06 11:44:43.671: D/Volley(6541): [1] MarkerLog.finish: (+9   ) [1059] cache-hit-parsed
  5. 04-06 11:44:43.671: D/Volley(6541): [1] MarkerLog.finish: (+1   ) [1059] post-response
  6. 04-06 11:44:43.681: D/Volley(6541): [1] MarkerLog.finish: (+0   ) [ 1] done
  7. 04-06 11:44:43.691: V/com.lms.volleydemo(6541): Has Cache-Control
  8. 04-06 11:44:43.691: V/com.lms.volleydemo(6541): Max AGe = 31536000
  9. 04-06 11:44:43.691: V/com.lms.volleydemo(6541): SoftExpire = 1428291883693
  10. 04-06 11:44:43.691: V/com.lms.volleydemo(6541): Completely unexpired cache hit. http://img.my.csdn.net/uploads/201403/03/1393854094_4652.jpg

可以看到Volley的确是可以从缓存中拿出图片数据来展示的,相信对于这个问题的答案,那位朋友应该也了解了吧。

那么我们再来看看Json数据的log吧,如下:

[java] view plain copy  
  1. 04-06 12:18:37.521: V/com.lms.volleydemo(6541): cache-hit-expired for request http://www.weather.com.cn/data/sk/101280101.html
  2. 04-06 12:18:37.551: D/Volley(6541): [1] MarkerLog.finish: (99   ms) [ ] http://www.weather.com.cn/data/sk/101280101.html 0x88751869 NORMAL 27
  3. 04-06 12:18:37.551: D/Volley(6541): [1] MarkerLog.finish: (+0   ) [ 1] add-to-queue
  4. 04-06 12:18:37.551: D/Volley(6541): [1] MarkerLog.finish: (+1   ) [1059] cache-queue-take
  5. 04-06 12:18:37.551: D/Volley(6541): [1] MarkerLog.finish: (+74  ) [1059] cache-hit-expired
  6. 04-06 12:18:37.551: D/Volley(6541): [1] MarkerLog.finish: (+1   ) [1062] network-queue-take
  7. 04-06 12:18:37.551: D/Volley(6541): [1] MarkerLog.finish: (+20  ) [1062] post-error
  8. 04-06 12:18:37.551: D/Volley(6541): [1] MarkerLog.finish: (+3   ) [ 1] done
  9. 04-06 12:18:38.683: D/memalloc(6541): ion: Mapped buffer base:0x5c2a9000 size:3768320 offset:0 fd:51

在飞行模式下,我们看到它首先是cache_hit_expired,然后才会去网络获取数据,但是因为没有连网,所以就会出现错误,它就获取不到数据了。

那么Volley中是如何判断expired的数据的呢,如下:

[java] view plain copy  
  1. /** True if the entry is expired. */
  2. public boolean isExpired() {
  3. return this.ttl < System.currentTimeMillis();
  4. }

而ttl的值就是上面parseCacheHeader中的softExpire的值了,这个值是由缓存中的MaxAge的值来计算的,但其实所有这些都是从Response中取出来的值。

对应于我们demo中的天气预报的url,通过网络传回来的response是没有cache-control的,所以它的maxAge也就是0了,从而导致ttl的值也一直是0,所以就一直是过期的,需要去从网张中获取。

我觉得这是因为天气是瞬息万变的,搞缓存是没有意义的,而对于其它的json数据,其实取决于服务器传回来的Header信息中CacheControl的信息。

当然,如果真想自己缓存,又不想它过期,可以把Volley的源代码也导入项目中,修改源代码也是可以的,不过这就。。。。

源代码下载!

Android中关于Volley的使用(八)缓存机制的深入认识相关推荐

  1. Android中关于Volley的使用(四)利用NetworkImageView来加载图片

    在使用Volley来从网络获取图片的时候,我们前面介绍了ImageRequest的使用,而其实Volley还提供了一个NetworkImageView类.利用这个类,我们可以更有效率地去从网络去获取图 ...

  2. Android中关于Volley的使用(二)加载Json数据

    前面一篇关于Volley的文章中,我们学习了如何利用ImageRequest去网络中加载图片,那么今天我们就来学习一下如何利用volley去网络中加载Json格式数据,并将其展示在一个ListView ...

  3. Android中关于Volley的使用(一)加载图片

    在Android中,如果我们要展示的图片是存储在网络上的时候,我们就必须通过HttpClient或者HttpUrlConnection这两个类来进行关于网络方面的操作,比如下面中利用GridView来 ...

  4. android中的定时任务一般有两种机制,android 定时任务

    使用timertask进行定时任务 首先创建TimerTask: class SynchroTimerTask extends TimerTask { @Override public void ru ...

  5. Android中关于Volley的使用(三)认识Volley的架构

    前面我们讲了怎么应用Volley从网络获取图片跟JSON数据,具体的应用如下: 1)通过Volley类获得一个RequestQueue对象: mQueue = Volley.newRequestQue ...

  6. Android中使用Volley开源库进行Http网络请求(GET方式)

    在之前的Http网络请求中,我们一般使用输入流以及缓冲区的方式进行访问,然后从服务器获取返回的数据.代码行数近20行,而且网络操作是放在Thread线程中进行的,对于Java或者Android的线程还 ...

  7. android清除缓存有哪些,Android中的清除数据和清除缓存有什么区别,它们分别清除了哪些文件...

    清除数据和清除缓存的区别 反射调用系统隐藏接口,需要准备的东西: 一.在AndroidManifest.xml中的manifest标签下添加声明 android:sharedUserId=" ...

  8. Android中使用Volley开源库进行Http网络请求(POST方式)

    之前使用了开源网络请求库Volley进行了Http GET请求.这次我们讨论使用Volley进行POST请求.POST请求比GET稍微复杂一点点.可以认为是建立在GET的基础上.POST使发送的url ...

  9. android开发 app消息提醒功能,Android中利用App实现消息推送机制的代码

    1.消息推送机制 服务器器端需要变被动为主动,通知客户一些开发商认为重要的信息,无论应用程序是否正在运行或者关闭. 我想到了一句话:don't call me,i will call you! qq今 ...

最新文章

  1. Linux 的权限表达式
  2. 在vscode中怎样debug调试go程序
  3. java Web程序使用wro4j合并、压缩js、css等静态资源
  4. 转 使用vim时按了CTRL+S键怎么办?
  5. Windows Server 2008 安装详细流程 解说
  6. 华为防火墙管理员角色和级别详解
  7. Hyperledger Fabric教程(15)--基于Kafka的Order服务实战
  8. easyui图标对照 --由于文章历史久远, 博主放弃治疗了
  9. Javashop 7.0 支付成功以后库里面没有记录问题
  10. PROFINET 模拟器使用教程
  11. java structs_java深入探究12-框架之Structs
  12. ubuntu18之wine
  13. ti ds90ub953 与ds90ub954 、ds90ub933的调试总结
  14. mixly编程怎样音乐_使用mixly和Arduino结合蜂鸣器播放音乐
  15. git解决拉取代码本地代码未提交
  16. 题解 洛谷 P4042 [AHOI2014/JSOI2014]骑士游戏
  17. 截至2017 年 2 月全球桌面操作系统市场份额:Linux 占 2.05%...
  18. PostGIS 查询某点周围指定范围内的兴趣点
  19. Java 笔试:常见题目总结,android混合开发lua
  20. UPC10525: Dove 打扑克

热门文章

  1. 程序员必备的英语词汇 (1)
  2. VCA821,VCA824做程控放大器使用总结
  3. Python 自动化办公(一)
  4. 用KFServing加速联邦学习模型的部署
  5. Android:应用程序转移到USB存储器(SD卡)
  6. 基于c#开发海康工业相机
  7. 初学者入门基础经典SQL练习题(MySQL精简版)
  8. 电影流浪地球2投资成本多少?如何参与投资?风险系数高吗?
  9. MFC中使用SKIN++
  10. android刮奖控件,资深程序员教你一步步打造万能的Android刮奖控件