AndroidCache:一个带过时自动执行删除的本地缓存工具

576 阅读2分钟

前言:

鉴于开发时候,经常出现相同的素材图片,经过相同的转换以及压缩率输入到本地Cache文件内,并没有及时的清理,导致大量的旧文件生成,而Github上不少的库都有类似过时的处理操作,但都是惰性的处理,即相同Key的文件如果一旦未被再次调用,则不会触发过时删除的处理,这也不是及时解决包体越来越大的问题。

简述原理:

如何记录这些文件生成的,一开始想法是通过MMKV进行KEY的记录,但发现如果携带信息后,进Value的反序列化以及存入value前先序列化变成字符串,这个操作的不方便,还不如直接采用数据库进行处理,相对可能会慢点。
数据库表的设计:

@Entity
class SourceInfo(
    @PrimaryKey val md5Name: String,
    val compress: Int = 100,
    val path: String,
    val finalMd5: String,
    var usingCount :Int = 1
)

这里利用到Room数据库进行管理,通过MD5值,以及压缩率作为条件去记录文件路径,usingCount作为文件被调用的次数统计,方便后续删除进行判断依据,如Bitmap的MD5计算:

val md5Name = Util.value2MD5(ByteBuffer.allocate(bitmap.byteCount).let {
                bitmap.copyPixelsToBuffer(it)
                it.array()
            }) + "[${bitmap.width}X${bitmap.height}X${format.name}]"

这个md5Name作为数据的主键存入,带上了参数和文件压缩方式,作为唯一的判断

DataHelper.getDao()
            .getSourceInfo(md5Name, quality)
            

调用数据库,去查找记录,当存在记录且本地文件存在时候,直接返回本地文件,而无需再次写入到本地目录。

定时删除

借助官方Workmanager的后台任务,对记录进行检查并删除过时文件,扫描检查时候,内容的usingCount会-1,当低于某一个值后,则会下一次任务到来时删除该本地文件,默认任务时间为15分钟,WorkManager的最低执行间隔时间。

举例使用

Asset文件按顺序输入到缓冲目录同一个文件内。

GlobalScope.launch(Dispatchers.IO) {
                CacheFlow.streamToCache(resources.assets.open("text.txt"))
                    .flatMapConcat { CacheFlow.streamAppendCache(resources.assets.open("text.txt"),it!!) }
                    .flatMapConcat { CacheFlow.streamAppendCache(resources.assets.open("text2.txt"),it!!) }
                    .collect {
                    }
            }

结尾

其实这个库是用来举例处理这种类似的包体因为缓存文件过多而设计的,其实我们更多应该是开发时候注意这些规范,我们可以采取临时缓存文件如果属于一次性的,则马上进行删除,不应该直接放到缓存目录里。而本库的初衷是考虑到,一种场景就是:相同的文件需要再次上传到网络,而上传前需要从其他地方写入到缓冲目录的,缓冲目录作为临时存放的地点,存在不确定的是否会再次上传的情况,而进行延后按条件删除。