Volley详解(四)——缓存(Cache)
来源:互联网 发布:bad air sponge 知乎 编辑:程序博客网 时间:2024/06/06 15:28
概述
本篇介绍缓存相关的类,包括Cache
、DiskBasedCache
、CacheDispatcher
。
Part 1 ——Cache
表示缓存的接口,这也体现了扩展性,只给出存取接口,而没有具体实现,虽然Volley
中只给了一中实现,即DiskBasedCache
,但客户端在调用时仍然只与接口打交道,如果想用其他的缓存方式,只需要自己实现Cache
接口即可,完全不影响客户端的工作。
内部类Entry
静态内部类Cache$Entry
,表示具体的缓存内容,主要属性:
byte[] data
:响应的主体long serverDate
:服务器返回数据的时间long lastModified
:内容最后更新的时间long ttl
:数据保质期Map<String, String> responseHeaders
:响应的头信息
主要方法
Cache
接口主要有如下方法:
Entry get(String key);
根据key获取缓存内容put(String key, Entry entry);
向缓存中写入内容remove(String key);
删除缓存条目clear();
清空缓存
Part 2 ——DiskBasedCache
Volley
中Cache
接口的唯一默认实现,用文件存储的方式实现,并根据最近最少使用(LRU)原则限制缓存容量。
内部类CacheHeader
定义了内部类DiskBasedCache$CacheHeader
,从名字可以看出该类存储的主要是header
,实际上,它的多数成员都与Cache$Entry
类相同,比如头信息和过期策略相关的信息等,唯一不同的是,该类不包含byte[] data
,也就是响应的内容主体,很好理解,因为既然是基于Disk
的,那这部分内容显然是要放在文件里的。
其实,CacheHeader
类起到了索引的作用,辅助信息除了写入文件,还要放在CacheHeader
类中,也就是在内存里。
这样做的合理性一目了然:
CacheHeader
里的信息会被更频繁地用到,比如判断缓存是否存在、是否过期,每次访问缓存,都要先查询这些辅助信息;而且这些辅助信息占用空间很小。因此,这部分放在内存。
DiskBasedCache
中维护了一个Map<String,CacheHeader> mEntries
,用来作缓存索引。
get()
和put()
这是读写缓存的方法,二者思路大同小异。在DiskBasedCache
中,Entry
实际上起到了中间层的作用,这是与外界的交换方式,而CacheHeader
和File是DiskBasedCache
内部的存储方式。
用put()
写入缓存时,先根据cacheKey
找到对应的文件,然后依次向文件写入Header
和body
,最后将Header
加入到mEntries
中作为索引。
用get()
读取缓存时,先从mEntries
中查找所需内容是否存在、是否过期。
- 如果缓存存在且未过期,则从
mEntries
中获取CacheHeader
,然后根据cacheKey
找到对应的文件,从文件获取body
,将CacheHeader
和body
组合成Cache$Entry
并返回结果; - 如果缓存不存在或过期,则直接将该请求放入网络请求队列,等待网络分发线程处理。
缓存空间限制
DiskBasedCache
中用作索引的对象是mEntries
,它是由LinkedHashMap
实现的,而且存储顺序是访问顺序accessOrder
(与插入顺序insertOrder
相对),可以实现最近最少使用(LRU)原则。
实现控制缓存大小的函数是
private void pruneIfNeeded(int neededSpace);
每次需要写入缓存之前,该函数会根据本次写入所需的空间判断是否需要进行清理缓存。如果需要清理,则获取mEntries
的iterator
,依次删除索引及对应的文件,知道缓存空间低于限制的最大空间。
对于以accessOrder作为访问顺序的
LinkedHashMap
,iterator
会按照最近访问的时间顺序进行遍历,最长时间没有被访问过的条目会被最先遍历到。因此该数据结构可以直接用来实现LRU Cache。
Part 3 ——CacheDispatcher
缓存分发线程,继承了Thread
,维护了缓存请求队列mCacheQueue
,网络请求队列mNetworkQueue
,缓存mCache
,响应分发对象mDelivery
等,负责从缓存请求队列mCacheQueue
中依次获取请求并进行处理,如果队列为空,则阻塞,直到队列不为空。
对于获取到的每个Request
,从mCache
查找缓存,如果获取到了未过期的缓存,则将得到的Cache$Entry
构造成NetworkResponse
对象,交给mDelivery
进行毁掉处理。
如果在mCache
中没有找到缓存,则将该请求放入mNetworkQueue
,等待网络分发线程处理。
如果在mCache
中找到了过期的缓存,则除了将请求放入mNetworkQueue
之外,还要删除mCache
中过期的缓存。
- Volley详解(四)——缓存(Cache)
- mybatis缓存机制详解(一)——Cache
- Volley Cache缓存机制
- Android Volley详解(四) 源码分析
- 【Cache】web缓存详解 (转载)
- yii中缓存(cache)详解
- yii中缓存(cache)详解
- ASP.NET——缓存(cache)
- 谷歌Volley网络框架分析。(四)缓存机制
- Android volley 解析(四)之缓存篇
- Android volley 解析(四)之缓存篇
- Android volley 解析(四)之缓存篇
- Android volley 解析(四)之缓存篇
- Android volley 解析(四)之缓存篇
- Android volley 解析(四)之缓存篇
- Android volley 解析(四)之缓存篇
- Android volley 解析(四)之缓存篇
- Volley(3)—图片缓存及NetWorkIamgeView控件
- Java类的初始化、继承
- 什么是粗粒度与细粒度,它们的区别又是什么?
- 九度 Online Judge 算法 刷题 题目1056:最大公约数
- 【读书笔记】iOS-Xcode-查找特殊字符的方法
- Knockout.js on the way
- Volley详解(四)——缓存(Cache)
- he
- 通过lldb远程调试iOS App
- 4.2 虚拟成员函数
- FMDB简单应用
- servlet
- DroidBox 环境搭建 【图文】
- 使用fis对资源进行打包、压缩、合并、加MD5发布
- 用户登陆登出日志