DiskLruCache
2015-06-04 21:42
260 查看
DiskLruCache
非Google官方编写,但获得官方认证https://github.com/JakeWharton/DiskLruCache
compile 'com.jakewharton:disklrucache:2.0.2'
使用方法
构造函数私有,只能通过open() 方法创建实例/sdcard/Android/data/package name/cache
/data/data/package name/cache
public static DiskLruCache open( File directory, // 存放路径 int appVersion, // 当前应用的版本号,每当版本号改变缓存路径下的数据都会被清除掉 int valueCount, // 同一个key可以对用多少个缓存文件,一般传1 long maxSize // 最多可以缓存多少字节 Integer.MAX_VALUE ){}
写入 Edit
DiskLruCache.Editor edit = diskLruCache.edit("cache_1"); // key,对应文件cache_1.0 OutputStream os = edit.newOutputStream(0); // 对应1个key可以缓存多个文件 // 流对拷... edit.commit(); // edit.abort();
读取 Snapshot 此时对该数据进行更新和删除对次没有影响
DiskLruCache.Snapshot snapshot = diskLruCache.get("cache_1"); InputStream is = snapshot.getInputStream(0);
删除
diskLruCache.remove("cache_1");
清空
diskLruCache.delete();
原理
概述
---get() ---> Snapshot --- getInputStream() ---> InputStream | DiskLruCache.open()/delete() | --- edit() ---> Editor --- newOutputStream() ---> OutputStrem
journal
libcore.io.DiskLruCache1
1
1
DIRTY cache_1
CLEAN cache_1 107
REMOVE cache_1
open() 的时候如果存在journal文件,readJournal() 一行行读取
String magic = reader.readLine(); // libcore.io.DiskLruCache:固定值 String version = reader.readLine(); // 1:DiskLruCache 版本号 String appVersionString = reader.readLine(); // 1:传入的App版本号 String valueCountString = reader.readLine(); // 1:传入的一个key对应几个文件 String blank = reader.readLine();
如果发现以上这些元素和open() 时传入的参数不一致,就抛出IOE,open() 中捕获后会清空该目录delete() ,并重建rebuildJournal()
private Writer journalWriter;
get()
journalWriter.append(READ + ' ' + key + '\n');
commit()
journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
remove()
journalWriter.append(REMOVE + ' ' + key + '\n');
LinkedHashMap
private final LinkedHashMap<String, Entry> lruEntries = new LinkedHashMap<String, Entry>(0, 0.75f, true); private final class Entry { private final String key; // getCacheFile(); getDirtyFile(); private final long[] lengths; private boolean readable; private Editor currentEditor; private long sequenceNumber; }
edit() 的时候先new Entry() 放入容器,再创建Editor(),edit写入的是dirtyFile(key + “.” + i + “.tmp”)
commit() 的时候把dirtyFile从命名为cacheFile(key + “.” + i),同时将entry关联的editor 置为null,切断关联entry.currentEditor = null;
// 部分代码 public synchronized Snapshot get(String key) throws IOException { Entry entry = lruEntries.get(key); InputStream[] ins = new InputStream[valueCount]; for (int i = 0; i < valueCount; i++) { ins[i] = new FileInputStream(entry.getCleanFile(i)); } return new Snapshot(key, entry.sequenceNumber, ins, entry.lengths); } public final class Snapshot implements Closeable { private final String key; private final long sequenceNumber; private final InputStream[] ins; private final long[] lengths; public InputStream getInputStream(int index) { return ins[index]; } public void close() { for (InputStream in : ins) { Util.closeQuietly(in); } } }
清理工作
写入日志的通知,判断是否需要清理日志文件和集合对象// 对应日志的次数,每写入、删除、读取一次都+1,直到2000时对journal重构一次,避免文件过大 private int redundantOpCount; // 清理线程 final ThreadPoolExecutor executorService = new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); // 清理条件 private boolean journalRebuildRequired() { final int redundantOpCompactThreshold = 2000; return redundantOpCount >= redundantOpCompactThreshold // && redundantOpCount >= lruEntries.size(); } // 具体的清理工作 public Void call() throws Exception { synchronized (DiskLruCache.this) { if (journalWriter == null) { return null; // Closed. } trimToSize(); if (journalRebuildRequired()) { rebuildJournal(); redundantOpCount = 0; } } return null; }
相关文章推荐
- BZOJ 1668: [Usaco2006 Oct]Cow Pie Treasures 馅饼里的财富( dp )
- STL之deque
- MySQL日期时间函数大全
- c#自动更新+安装程序的制作
- hdu 2899 二分
- 矩形面积并 (hdu1542)
- Eclipse配置PyDev插件
- P122.43
- Java程序设计 实验三
- 没有不留痕迹的事
- hidden_frame实现不刷新上传文件
- glusterfs复制卷的创建以及glusterfs的常用命令
- 多条命令中的逻辑运算符和括号 “||” “&&” () Linux
- js中date与String转换
- 几种常见模式识别算法整理和总结
- 团队项目作业第五项:给出设计类图
- 不能因为为了添加一个新功能,影响到旧的功能
- android调用百度地图定位与附近搜索
- Android流量监控
- java基础整理——集合