新闻中心
你的位置:kaiyun在线登录网址 > 新闻中心 >kaiyun官方网站 Android能手进阶之透澈了解DiskLruCache磁盘缓存机制道理
发布日期:2023-12-09 13:04 点击次数:103
[[423666]]
弁言
DiskLruCache是一种贬责数据存储的时期,单从Cache的字面真义也不错意会到kaiyun官方网站,"Cache","高速缓存";
之前咱们先容过lrucache,莫得看过老铁,不错从历史记载看;
今天咱们来从源码上分析下DiskLruCache;
Android进阶之透澈意会LruCache缓存机制道理
一、为什么用DiskLruCache 1、LruCache和DiskLruCacheLruCache和DiskLruCache两者齐是利用到LRU算法,通过LRU算法对缓存进行贬责,以最近最少使用算作贬责的依据,删除最近最少使用的数据,保留最近最常用的数据;
LruCache垄断于内存缓存,而DiskLruCache是存储树立缓存;
2、为何使用DiskLruCache离线数据存在的道理,当无收罗大概是收罗现象不好时,APP照旧具备部分功能是一种很好的用户体验;
假定网易新闻这类新闻客户端,数据绝对存储在缓存中而不使用DiskLruCache时期存储,那么当客户端被捐躯,缓存被开释,意味着再次掀开APP将是一派空缺;
另外DiskLruCache时期也可为app“离线阅读”这一功能作念时期提拔;
DiskLruCache的存储旅途是不错自界说的,不外也不错是默许的存储旅途,而默许的存储旅途一般是这么的:/sdcard/Android/data/包名/cache,包名是指APP的包名。咱们不错在手机上掀开,浏览这一说念径;
二、DiskLruCache使用 1、添加依赖// add dependence implementation 'com.jakewharton:disklrucache:2.0.2'2、创建DiskLruCache对象
/* * directory – 缓存目次 * appVersion - 缓存版块 * valueCount – 每个key对应value的个数 * maxSize – 缓存大小的上限 */ DiskLruCache diskLruCache = DiskLruCache.open(directory, 1, 1, 1024 * 1024 * 10);3、添加 / 得回 缓存(一双一)
/** * 添加一条缓存,一个key对应一个value */ public void addDiskCache(String key, String value) throws IOException { File cacheDir = context.getCacheDir(); DiskLruCache diskLruCache = DiskLruCache.open(cacheDir, 1, 1, 1024 * 1024 * 10); DiskLruCache.Editor editor = diskLruCache.edit(key); // index与valueCount对应,永别为0,1,2...valueCount-1 editor.newOutputStream(0).write(value.getBytes()); editor.commit(); diskLruCache.close(); } /** * 得回一条缓存,一个key对应一个value */ public void getDiskCache(String key) throws IOException { File directory = context.getCacheDir(); DiskLruCache diskLruCache = DiskLruCache.open(directory, 1, 1, 1024 * 1024 * 10); String value = diskLruCache.get(key).getString(0); diskLruCache.close(); }4、添加 / 得回 缓存(一双多)
/** * 添加一条缓存,1个key对应2个value */ public void addDiskCache(String key, String value1, String value2) throws IOException { File directory = context.getCacheDir(); DiskLruCache diskLruCache = DiskLruCache.open(directory, 1, 2, 1024 * 1024 * 10); DiskLruCache.Editor editor = diskLruCache.edit(key); editor.newOutputStream(0).write(value1.getBytes()); editor.newOutputStream(1).write(value2.getBytes()); editor.commit(); diskLruCache.close(); } /** * 添加一条缓存,1个key对应2个value */ public void getDiskCache(String key) throws IOException { File directory = context.getCacheDir(); DiskLruCache diskLruCache = DiskLruCache.open(directory, 1, 2, 1024); DiskLruCache.Snapshot snapshot = diskLruCache.get(key); String value1 = snapshot.getString(0); String value2 = snapshot.getString(1); diskLruCache.close(); }三、源码分析 1、open()
DiskLruCache的构造程序是private修饰,这也便是告诉咱们,不成通过new DiskLruCache来得回实例,构造程序如下:
private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) { this.directory = directory; this.appVersion = appVersion; this.journalFile = new File(directory, JOURNAL_FILE); this.journalFileTmp = new File(directory, JOURNAL_FILE_TEMP); this.journalFileBackup = new File(directory, JOURNAL_FILE_BACKUP); this.valueCount = valueCount; this.maxSize = maxSize; }
然而提供了open()程序,供咱们得回DiskLruCache的实例,open程序如下:
/** * Opens the cache in {@code directory}, creating a cache if none exists * there. * * @param directory a writable directory * @param valueCount the number of values per cache entry. Must be positive. * @param maxSize the maximum number of bytes this cache should use to store * @throws IOException if reading or writing the cache directory fails */ public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize) throws IOException { if (maxSize <= 0) { throw new IllegalArgumentException("maxSize <= 0"); } if (valueCount <= 0) { throw new IllegalArgumentException("valueCount <= 0"); } // If a bkp file exists, use it instead. //看备份文献是否存在 File backupFile = new File(directory, JOURNAL_FILE_BACKUP); //如若备份文献存在,而且日记文献也存在,就把备份文献删除 //如若备份文献存在,日记文献不存在,就把备份文献重定名为日记文献 if (backupFile.exists()) { File journalFile = new File(directory, JOURNAL_FILE); // If journal file also exists just delete backup file. // if (journalFile.exists()) { backupFile.delete(); } else { renameTo(backupFile, journalFile, false); } } // Prefer to pick up where we left off. //运行化DiskLruCache,包括,大小,版块,旅途,key对应几许value DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize); //如若日记文献存在,就动手赌文献信息,并复返 //主要便是构建entry列表 if (cache.journalFile.exists()) { try { cache.readJournal(); cache.processJournal(); return cache; } catch (IOException journalIsCorrupt) { System.out .println("DiskLruCache " + directory + " is corrupt: " + journalIsCorrupt.getMessage() + ", removing"); cache.delete(); } } //不存在就新建一个 // Create a new empty cache. directory.mkdirs(); cache = new DiskLruCache(directory, appVersion, valueCount, maxSize); cache.rebuildJournal(); return cache; }
open函数:如若日记文献存在,径直去构建entry列表;如若不存在,就构建日记文献;
2、rebuildJournal()构建文献: //这个便是咱们不错径直在disk内部看到的journal文献 主要便是对他的操作 private final File journalFile; //journal文献的temp 缓存文献,一般齐是先构建这个缓存文献,恭候构建完成以后将这个缓存文献重新定名为journal private final File journalFileTmp; /** * Creates a new journal that omits redundant information. This replaces the * current journal if it exists. */ private synchronized void rebuildJournal() throws IOException { if (journalWriter != null) { journalWriter.close(); } //指向journalFileTmp这个日记文献的缓存 Writer writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(journalFileTmp), Util.US_ASCII)); try { writer.write(MAGIC); writer.write("\n"); writer.write(VERSION_1); writer.write("\n"); writer.write(Integer.toString(appVersion)); writer.write("\n"); writer.write(Integer.toString(valueCount)); writer.write("\n"); writer.write("\n"); for (Entry entry : lruEntries.values()) { if (entry.currentEditor != null) { writer.write(DIRTY + ' ' + entry.key + '\n'); } else { writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n'); } } } finally { writer.close(); } if (journalFile.exists()) { renameTo(journalFile, journalFileBackup, true); } //是以这个地点 构建日记文献的历程主要便是先构建出日记文献的缓存文献,如若缓存构建告捷 那就径直重定名这个缓存文献,这么作念克己在那边? renameTo(journalFileTmp, journalFile, false); journalFileBackup.delete(); //这里亦然把写入日记文献的writer运行化 journalWriter = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(journalFile, true), Util.US_ASCII)); }
再来看当日记文献存在的时代kaiyun官方网站,作念了什么
3、readJournal()private void readJournal() throws IOException { StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile), Util.US_ASCII); try { //读日记文献的头信息 String magic = reader.readLine(); String version = reader.readLine(); String appVersionString = reader.readLine(); String valueCountString = reader.readLine(); String blank = reader.readLine(); if (!MAGIC.equals(magic)
相关资讯
- 2024/09/19kaiyun体育这背后是乳成品行业正受需求颓落、奶源富裕双重夹攻-kaiyun在线登录网址
- 2024/09/19kaiyun体育该基金将进行收益分派-kaiyun在线登录网址
- 2024/09/19kaiyun官方网站报37.155好意思元-kaiyun在线登录网址
- 2024/09/19kaiyun官方网站和当下的品牌在会员营销流于体式作念名义著作不同样-kaiyun在线登录网址
- 2024/09/19kaiyun官方网站“潜在买家在评估股权时-kaiyun在线登录网址