具体解说Android的图片下载框架UniversialImageLoader之磁盘缓存的扩展(二)
相对于第一篇来讲,这里讲的是磁盘缓存的延续。在这里我们主要是关注四个类。各自是DiskLruCache、LruDiskCache、StrictLineReader以及工具类Util。
接下来逐一的对它们进行剖析。
废话不多说。
首先来看一下DiskLruCache。
这个类的主要功能是什么呢?我们先来看一段类的凝视:
- /**
- * A cache that uses a bounded amount of space on a filesystem. Each cache
- * entry has a string key and a fixed number of values. Each key must match
- * the regex <strong>[a-z0-9_-]{1,64}</strong>. Values are byte sequences,
- * accessible as streams or files. Each value must be between {@code 0} and
- * {@code Integer.MAX_VALUE} bytes in length.
- * <p>This class is tolerant of some I/O errors. If files are missing from the
- * filesystem, the corresponding entries will be dropped from the cache. If
- * an error occurs while writing a cache value, the edit will fail silently.
- * Callers should handle other problems by catching {@code IOException} and
- * responding appropriately.
- */
对英文不感兴趣的童鞋别急,以下略微翻译一下:
这是基于文件系统所构建的一个基于有限空间的缓存。每个缓存入口都有一个字符串秘钥与固定的数字的序列。每个秘钥一定要与正則表達式<strong>[a-z0-9_-]{1,64}</strong>进行匹配。数值则是一些字节序列,是能够作为流或者文件被訪问的。每个数值在长度上一定是在0与最大的整数之间的。这个缓存类对部分的I/O操作室容忍的。假设有一些文件从文件系统中丢失,对应的缓存的入口ᐟ会从缓存中移除。
假设在写入一个缓存的数值的时候发生了以外的错误,
当前的编辑也会默默的撤销,回调者则会通过捕获一些I/O异常与核实的回应来处理一些其它的问题。
因为DiskLruCache的代码量较多,我们还是从一些核心的变量与方法上来讲述它。核心变量例如以下:
- static final String JOURNAL_FILE = "journal";
- static final String JOURNAL_FILE_TEMP = "journal.tmp";
- static final String JOURNAL_FILE_BACKUP = "journal.bkp";
- static final String MAGIC = "libcore.io.DiskLruCache";
- static final String VERSION_1 = "1";
- static final long ANY_SEQUENCE_NUMBER = -1;
- static final Pattern LEGAL_KEY_PATTERN = Pattern.compile("[a-z0-9_-]{1,64}");
- private static final String CLEAN = "CLEAN";
- private static final String DIRTY = "DIRTY";
- private static final String REMOVE = "REMOVE";
- private static final String READ = "READ";
- private final File directory;
- private final File journalFile;
- private final File journalFileTmp;
- private final File journalFileBackup;
- private final int appVersion;
- private long maxSize;
- private int maxFileCount;
- private final int valueCount;
- private long size = 0;
- private int fileCount = 0;
- private Writer journalWriter;
- private final LinkedHashMap<String, Entry> lruEntries =
- new LinkedHashMap<String, Entry>(0, 0.75f, true);
- private int redundantOpCount;
- private long nextSequenceNumber = 0;
- final ThreadPoolExecutor executorService =
- new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
上面的变量大致进行归类。包含:日志文件的命名。日志文件的開始5行内容的变量的定义,文件尺寸与数量的限制以及一个LinkedHashMap来维持一个缓存队列,最后另一个线程池。
接下来大致介绍一下里面的函数的功能:
1、readJournal 这个函数的功能是1、计算当前的日志的缓存的行数、2、计算当前的缓存的日志文件里冗余的行数 3、读取而且处理缓存的日志中的每一行的数据
2、readJournalLine 这个函数的功能是真正的运行每一行日志的操作 当在日志中遇到一个keyword的时候,从当前的缓存的度列中查看当前的keyword所映射的对象是否存在,假设不存在。以当前的keyword创建一个新的对象而且放到当前的缓存的队列中。
3、processJournal 计算初始化的尺寸,而且回收缓存中的一些垃圾。脏的入口将会被觉得是前后矛盾的,将会被回收。
4、rebuildJournal 这个函数的功能是创建一个新的删除大量冗余信息的日志文件,假设当前的日志文件存在。将会替换掉当前的日志文件。
5、
- public synchronized Snapshot get(String key) throws IOException
这个函数的功能是返回一个命名为key的文件入口的快照。而且假设当前的数值是返回的,那么它将会被移动到LRU队列的头部。
6、
- public synchronized boolean remove(String key) throws IOException
假设当前的文件实体是存在的而且是可以删除的。那么就删除当前的文件的实体。当前正在被编辑的文件实体是不可以被删除的。
接下来关注一下这个类中的三个比較重要的内部类,各自是Snapshot、Editor与Entry。
大致介绍一些这三个类的功能。
Snapshot是缓存的文件实体的数值的一个快照。Editor是编辑缓存的文件实体的数值。
Entry是缓存的文件实体的数据模型。
接下来我们分下一下LruDiskCache这个类的主要功能。
正如这个类的名称一样,这是一个近期最久未使用的磁盘缓存。这样这个类的大致的功能我们清楚了。
我们会在这个类中看到这样一个成员变量
- protected DiskLruCache cache;
由此可见当前的类,是DiskLruCache针对磁盘缓存的接口的一个适配器。不信?我们从以下的方法中能够看出:
1、
- @Override
- public File getDirectory() {
- return cache.getDirectory();
- }
获取当前的缓存的文件夹。
2、
- public File get(String imageUri) {
- DiskLruCache.Snapshot snapshot = null;
- try {
- snapshot = cache.get(getKey(imageUri));
- return snapshot == null ? null : snapshot.getFile(0);
- } catch (IOException e) {
- L.e(e);
- return null;
- } finally {
- if (snapshot != null) {
- snapshot.close();
- }
- }
- }
通过图片的uri的对象获取图片文件的句柄。
是通过DiskLruCache中的快照实现的。
3、
- public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException {
- DiskLruCache.Editor editor = cache.edit(getKey(imageUri));
- if (editor == null) {
- return false;
- }
- OutputStream os = new BufferedOutputStream(editor.newOutputStream(0), bufferSize);
- boolean copied = false;
- try {
- copied = IoUtils.copyStream(imageStream, os, listener, bufferSize);
- } finally {
- IoUtils.closeSilently(os);
- if (copied) {
- editor.commit();
- } else {
- editor.abort();
- }
- }
- return copied;
- }
利用的是DiskLruCache中的文件编辑类Editor来讲当前的文件输入流写到生成的文件里。
其余的函数也是以此类推。
接下来要讲的类StrictLineReader。我们也是可将将其理解为一个帮助类,它是专门为读取缓存日志的内容而特别设计的。
主要观察以下的一个方法:
- public String readLine() throws IOException {
- synchronized (in) {
- if (buf == null) {
- throw new IOException("LineReader is closed");
- }
- if (pos >= end) {
- fillBuf();
- }
- for (int i = pos; i != end; ++i) {
- if (buf[i] == LF) {
- int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
- String res = new String(buf, pos, lineEnd - pos, charset.name());
- pos = i + 1;
- return res;
- }
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
- @Override
- public String toString() {
- int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
- try {
- return new String(buf, 0, length, charset.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e); // Since we control the charset this will never happen.
- }
- }
- };
- while (true) {
- out.write(buf, pos, end - pos);
- // Mark unterminated line in case fillBuf throws EOFException or IOException.
- end = -1;
- fillBuf();
- for (int i = pos; i != end; ++i) {
- if (buf[i] == LF) {
- if (i != pos) {
- out.write(buf, pos, i - pos);
- }
- pos = i + 1;
- return out.toString();
- }
- }
- }
- }
- }
在最后一个类Util中,主要是封装了三个方法。
1、readFully 从Reader中读取内容。而且拼接成为一个完整的字符串
2、deleteContents 迭代删除文件的文件夹的内容
3、closeQuietly 静默关闭文件流
Ok,关于磁盘存储的扩展就说到这里。希望对各位童鞋有所帮助。
具体解说Android的图片下载框架UniversialImageLoader之磁盘缓存的扩展(二)的更多相关文章
- 具体解说Android的图片下载框架UniversialImageLoader之磁盘缓存(一)
沉浸在Android的开发世界中有一些年头的猴子们,预计都可以深深的体会到Android中的图片下载.展示.缓存一直是心中抹不去的痛.鄙人亦是如此.Ok,闲话不说.为了督促自己的学习.以下就逐一的挖掘 ...
- 具体解说Android图片下载框架UniversialImageLoader之内存缓存(三)
前面的两篇文章着重介绍的是磁盘缓存,这篇文章主要是解说一下内存缓存.对于内存缓存.也打算分两篇文章来进行解说.在这一篇文章中,我们主要是关注三个类, MemoryCache.BaseMemoryCac ...
- AJ学IOS(55)多线程网络之图片下载框架之SDWebImage
AJ分享,必须精品 效果: 代码: - (NSArray *)apps { if (!_apps) { NSArray *dictArray = [NSArray arrayWithContentsO ...
- Android实现图片下载并保存SD卡
一.首先获取图片 //第一种获取图片的方法 String filePath = downloadUrl; //以下是取得图片的方法 取得的是InputStream,直接从InputStream生成bi ...
- Android自定义“图片+文字”控件四种实现方法之 二--------个人最推荐的一种
http://blog.csdn.net/yanzi1225627/article/details/8633872 第二种方法也要新建一个图片+文字的xml布局文件,然后写一个类继承自LinearLa ...
- 关于Exceptionless日志收集框架如何关闭磁盘缓存
问题:在使用Exceptionless的时候,Exception在收集到日志时会默认在appdata里面缓存当条日志的缓存文件,时间久了之后,如果收集到的日志越多磁盘的空间就会不足. 我使用的环境是 ...
- 【转】Picasso – Android系统的图片下载和缓存类库
来源:http://blog.chengyunfeng.com/?p=492 另一篇参考:http://blog.csdn.net/xu_fu/article/details/17043231 Pic ...
- Picasso – Android系统的图片下载和缓存类库
Picasso – Android系统的图片下载和缓存类库 Picasso 是Square开源的一个用于Android系统下载和缓存图片的项目.该项目和其他一些下载图片项目的主要区别之一是:使用4.0 ...
- Android常用优秀开源框架
Android常用优秀开源框架 https://github.com/Ericsongyl/AOSF AOSF:全称为Android Open Source Framework,即Android优秀开 ...
随机推荐
- 四、Solr数据源配置(JNDI、DIH)及定时重做索引
简介 Solr支持很多种创建索引的方式,包括网页,xml以及数据库,因为我这边做的是企业级的搜索,所以用的是数据库建立索引.其实从数据库建立索引,很大程度上取决于原来的数据库设计. 从数据库建立索引, ...
- C++ Win32控制台应用程序捕捉关闭事件
#include#includebool ctrlhandler( DWORD fdwctrltype ){ switch( fdwctrltype ) { // handle ...
- passwd-shadow文件
[root@rusky /]# vi /etc/passwd root:x:::Redhat5:/root:/bin/bash rusky:x::::/home/rusky:/bin/bash 1.r ...
- mybatis 与 反射
Mybatis是个优秀的ORM框架,所以它的反射层一定不会让我们失望 图比较大,可以开新页面查看 可以看到,Mybatis对这一块抽象的比较复杂,我们可以看到有几个比较主要的部分:Reflector. ...
- js精度丢失解决办法
/** * 加法运算,避免数据相加小数点后产生多位数和计算精度损失. * * @param num1加数1 | num2加数2 */ function numAdd(num1, num2) { var ...
- JS客户端读取Excel文件插件js-xls使用方法
js-xls是一款客户端读取Excel的插件,亲测IE11.FireFox.Chrome可用,读取速度也客观. 插件Demo地址:http://oss.sheetjs.com/js-xlsx/ ...
- The type or namespace name 'Script' does not exist in the namespace 'System.Web' (are you missing an assembly reference?)
应该说是 .net4 的bug,没有所谓的 System.Web.Extensions.dll 库文件,需要将项目的 Target Framework修改为 3.5版本,才能加载System.Web. ...
- JCo 指南
http://blog.csdn.net/asdfak/article/details/5834731 JAVA 调用SAP端接口 Java Connector and BAPI 前些日子想去深入的研 ...
- Popular Cows (POJ No.2186)
Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= ...
- Cocos2DX新手入门笔记索引
01--从根源种子CCNode说起 02—从Cocos2DX视角看游戏组成 03--理解HelloWorld结构 04--简单菜单使用 05--简单场景切换与精灵创建 06--触摸事件响应 07--动 ...