首先下定义:asimplecache是一款轻量的android缓存框架。可缓存的对象包括String、JSONObject、JSONArray、byte数组、Serializable数据、bitmap、drawable。
项目的链接:https://github.com/yangfuhai/ASimpleCache(作者杨福海)
项目就一个java文件,read the fucking source code也花不了多少时间,so let's go!

这是acache定义的唯一一个构造函数,这是一个私有的构造函数。acache提供了名为get的静态方法作为入口。

用户可以自定义缓存的最大容量和数量,当然也可以使用默认值,容量的默认值是50M,数量的默认值是最大整数(2147483647)。

这里,作者定义了一个hashmap来维护acache对象,根据进程的id来保证一个进程里对象是单例。如果当前进程里没有则创建对象并添加到名为mInstanceMap中。

cache的初始化过程,先是判断缓存目录是否存在,如果不存在就创建,如果创建失败就抛出异常。如果缓存目录准备好了,就创建一个缓存管理器:ACacheManager。所有的对象都是通过文件来保存的,而缓存的机制都是通过ACacheManager这个类实现的,接下来我们来学习下这个缓存管理器是怎样工作的。先来看一下它的构造函数:

可以看出构造函数对缓存目录、最大容量和最大数量做了初始化。在这里,cacheSize和cacheCount都是线程安全的,代表当前的缓存容量和缓存数量,这保证了多进程的文件操作的安全性。我们再来看看calculateCacheSizeAndCacheCount这个函数。

可以看出来,calculateCacheSizeAndCacheCount创建了一个新的线程,遍历的缓存目录下的所有文件,得到当前的缓存容量和数量。同时将维护一个hashmap保存file和对应的修改时间,后面将会根据这个hashmap来实现容量溢出处理的情况。ACacheManager提供了put、get、remove、clear、removeNext的操作。我们主要来看下put、get和removeNext三个方法。



可以看出,removeNext的作用就是移除最旧的文件,判断是否为最旧的依据就是通过file文件的lastModified值。每进行一次put和get方法都会更新key值对应文件的修改时间,当put更新时,会判断当前容量和数量加上新添加的文件大小是否小于最大容量和数量,如果不符合则删除不常用的文件直至符合,根据这个来保证缓存中存放的都是最常用的文件。看完了缓存管理器的机制,接下来我们来看看acache对外提供的put和get方法,方法比较多,就简单讲下string的存取:


可以看出,在put保存string信息时会根据key的hashcode返回一个file对象,通过覆盖的方式将信息更新到文件。在get中同样是读取file的文件流得到string信息。不过,在get中我们发现isDue这个函数,这个函数实际就是来判断文件是否过期的,acache还提供一个方法支持信息的有效期:

实现方法很简单,就是用户在设定了有效时间时,将时间信息写在文件的开头,在get读取信息时,会根据这个有效时间判断信息是否dirty,如果过期就删除并返回空。
通过这段代码可以更好得学习下文件缓存机制的原理,建议大家都去看看,而且总体来讲这个框架使用还是比较便捷的。另外,注意get和put方法是非线程安全的,使用的时候要注意这点。此外,个人觉得存在几个可以改进的点:
1、在读取string信息时使用string拼接字符串,信息量大的话会有性能损耗。
2、在put更新信息时,在做缓存判断时并没有考虑到信息覆盖的情况,在文件最大容量设置小的时候可能会有影响。
网友评论