Android 优化 - 磁盘缓存 DiskLruCache

一、概念

用于实现存储设备缓存,即磁盘缓存,通过将缓存对象写入文件系统从而实现缓存的效果。

二、使用

2.1 添加依赖

最新依赖

implementation "com.jakewharton:disklrucache:2.0.2"

2.2 配置权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2.3 创建对象 open()

public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
directory

存储路径,该文件夹里面所有文件参与计算大小。

appVersion应用的版本号,一般设为 1 即可。当版本号发生改变时会清空之前所有的缓存文件,而这个特性在实际开发中作用并不大,很多情况下即使应用的版本号发生了改变缓存文件却仍然是有效的。
valueCount表示同一个 key 可以对应多少个缓存文件,一般设为 1 即可。
maxSize表示缓存的总大小,比如 50MB,当缓存大小超出这个设定值后,DiskLruCache 会清除一些缓存从而保证总大小不大于这个设定值。
  • 缓存的key为String类型,且必须匹配正则表达式[a-z0-9_-]{1,64}。
  •  一个key可以对应多个value,value类型为字节数组,大小在0 ~ Integer.MAX_VALUE之间
  • 缓存的目录必须为专用目录,因为DiskLruCache可能会删除或覆盖该目录下的文件。
  • 添加缓存操作具备原子性,但多个进程不应该同时使用同一个缓存目录。 
/**
 * 外置路径:storage/emulated/0/Android/data/包名/cache
 * 内置路径:data/data/包名/ceche
 * @param cachePath 如果外置存储获取不到就从内置存储中获取,调用 context.externalCacheDir?.path ?: context.cacheDir.path
 */
class BitmapDiskCache(
    private val cachePath: String
) {
    private val cacheSize =  (1024 * 1024 * 50).toLong() //50M
    private val file = File(cachePath.plus("BitmapLru")).apply { if (!exists()) mkdirs() }
    private val instance = DiskLruCache.open(file, 1, 1, cacheSize)

    suspend fun write(key: String, value: Bitmap) = withContext(Dispatchers.IO) {
        val safeKey = toSafeKey(key)
        instance.use { cache ->
            //获取编辑器
            cache.edit(safeKey ).run {
                //获取输出流(0表示key对应的第一个缓存文件,不能超过创建时设置的valueCount)
                //实际使用时,根据写入的类型用需要的流再包装这个 OutputStream 后使用
                newOutputStream(0).use { outputStream ->
                    //写入Bitmap
                    value.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
                }
                //提交
                commit()
            }
        }
    }

    suspend fun read(key: String): Bitmap? = withContext(Dispatchers.IO) {
        val safeKey = toSafeKey(key)
        instance.use { cache ->
            //获取快照
            cache.get(safeKey ).run {
                //获取输入流(0表示key对应的第一个缓存文件,不能超过创建时设置的valueCount)
                //实际使用时,根据读取的类型用需要的流再包装这个 InputStream 后使用
                getInputStream(0).use { inputStream ->
                    //读取Bitmap
                    BitmapFactory.decodeStream(inputStream)
                }
            }
        }
    }

    suspend fun remove(key: String) = withContext(Dispatchers.IO) {
        instance.use { cache ->
            cache.remove(key)
        }
    }

    companion object {
        //MD5格式化成16进制的字符串,避免key有特殊字符串
        private fun toSafeKey(str: String): String {
            val byteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray())
            return BigInteger(1, byteArray).toString(16)
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中头像本地缓存可以通过使用SharedPreferences或者使用磁盘缓存的方式实现。 1. 使用SharedPreferences缓存头像: 可以将头像图片转化成Base64编码的字符串,然后将其保存在SharedPreferences中。当需要加载头像时,从SharedPreferences中读取Base64字符串,再将其转化为Bitmap对象。 具体实现代码如下: ``` //保存头像到SharedPreferences中 public void saveAvatarToSharedPreferences(Bitmap bitmap) { SharedPreferences sharedPreferences = getSharedPreferences("avatar", MODE_PRIVATE); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream); String avatarBase64 = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("avatar", avatarBase64); editor.apply(); } //从SharedPreferences中加载头像 public Bitmap loadAvatarFromSharedPreferences() { SharedPreferences sharedPreferences = getSharedPreferences("avatar", MODE_PRIVATE); String avatarBase64 = sharedPreferences.getString("avatar", null); if (avatarBase64 != null) { byte[] bytes = Base64.decode(avatarBase64, Base64.DEFAULT); return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } return null; } ``` 2. 使用磁盘缓存方式缓存头像: 可以使用Android中的LruCache或者DiskLruCache类来实现磁盘缓存头像。LruCache是一种内存缓存,而DiskLruCache则是一种磁盘缓存。 具体实现代码如下: ``` //初始化DiskLruCache private void initDiskLruCache() throws IOException { File cacheDir = getExternalCacheDir(); if (cacheDir != null) { int versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; diskLruCache = DiskLruCache.open(cacheDir, versionCode, 1, 10 * 1024 * 1024); } } //保存头像到DiskLruCache中 public void saveAvatarToDiskLruCache(String key, Bitmap bitmap) throws IOException { if (diskLruCache == null) { initDiskLruCache(); } if (diskLruCache != null) { DiskLruCache.Editor editor = diskLruCache.edit(key); if (editor != null) { OutputStream outputStream = editor.newOutputStream(0); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); editor.commit(); } } } //从DiskLruCache中加载头像 public Bitmap loadAvatarFromDiskLruCache(String key) throws IOException { if (diskLruCache == null) { initDiskLruCache(); } if (diskLruCache != null) { DiskLruCache.Snapshot snapshot = diskLruCache.get(key); if (snapshot != null) { InputStream inputStream = snapshot.getInputStream(0); return BitmapFactory.decodeStream(inputStream); } } return null; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值