
一、概念LruCache 是Android 3.1(API12)所提供的一个缓存类缓存到达限制的时候优先删除近期最少使用。内部维护了一个 LinkedHashMap 以访问顺序排列满了就删除尾元素即近期最少使用的Least Recently Used当获取缓存对象的同时会将该元素更新到队列头部。读写线程安全对缓存的元素是强引用不允许null键null值为null说明没有缓存。get()public final V get(K key)获取缓存过的数据不存在返回null。线程安全。put()public final V put(K key, V value)添加/更新缓存数据。线程安全。remove()public final V remove(K key)移除缓存的数据。evictAll()public final void evictAll()清除所有缓存数据resize()public void resize(int maxSize)重新设置最大缓存容量trimToSize()public void trimToSize(int maxSize)清除最老的缓存直到剩余缓存数量满足指定大小snapshot()public synchronized final MapK, V snapshot()返回一个Map集合元素按缓存访问次数最少到最多。二、使用设置 LruCache 缓存大小一般为当前进程可用内存的1/8。重写 sizeOf() 计算出要缓存的对象的大小总容量和对象大小计算的单位要一直一致。private val lruCache by lazy { //获取当前进程可用内存大小并分配1/8用于缓存 val cacheSize (Runtime.getRuntime().totalMemory() / 1024 / 8).toInt() object : LruCacheString, Bitmap(cacheSize) { //必须重写此方法来测量每张图片的大小单位要跟总缓存的单位一致 //如果是缓存简单的对象直接返回1 override fun sizeOf(key: String?, value: Bitmap?): Int { //返回Bitmap大小因为可以复用换成更小的图也还是占用原来的大小。 //而getByteCount()返回的是图片大小。 return value?.allocationByteCount ?: 0 } } } //提供存入方法 fun putBitmap(key: String, value: Bitmap) { lruCache.put(key, value) } //提供取出方法返回null意味着不存在缓存 fun getBitmap(key: String): Bitmap? { return lruCache.get(key) }三、封装3.1 工具类object RamCache { private val lruCache by lazy { //获取当前进程可用内存大小并分配1/8用于缓存 val cacheSize (Runtime.getRuntime().totalMemory() / 1024 / 8).toInt() object : LruCacheString, PairLong, Any(cacheSize) { //必须重写此方法来测量每个对象的大小单位要跟总缓存的单位一致 override fun sizeOf(key: String, value: PairLong, Any): Int { return 1 } } } //提供存入方法 fun put(key: String, value: PairLong, Any) { lruCache.put(key, value) } //提供取出方法返回null意味着缓存不存在或已过期 fun get(key: String): Any? if (key.isRamCacheExpired()) null else lruCache.get(key).second fun isExpored(key: String): Boolean { val before lruCache.get(key) return if (before null) { true } else { System.currentTimeMillis() - before.first 60000 //大于一分钟过期 } } }3.2 函数封装fetchData() 中对网络异常的处理详见。suspend fun T fetchData( request: suspend () - ApiResponseT ) runCatching { request() }.then { apiResponse - apiResponse.getData() }.onFailure { when (it) { //挂起函数作为检查点需要抛出 CancellationException 来停止后续代码的执行 is CancellationException - throw it } Log.e(获取数据失败, it.message.toString()) } /** * 先判断RAM缓存是否过期过期和不存在都返回false未过期就使用RAM缓存 * 过期就联网获取然后写入RAM缓存中 */ suspend fun T fetchDataWithRamCache( cacheName: String, request: suspend () - ApiResponseT, ) if (cacheName.isRamCacheExpired()) { //RAM缓存过期 fetchData(request).onSuccess { val value Pair(System.currentTimeMillis(), it as Any) RamCache.put(cacheName, value) } } else { //使用RAM缓存 val obj RamCache.get(cacheName) as T Result.success(obj) }