Kotlin Android缓存库CoroutinesCache

RxJava+Retrofit如果想做缓存以前会用RxCache(停止维护). 迁移到Kotlin后,使用Coroutines+Retrofit请求网络想做缓存的话貌似资料还不是不多.
CoroutinesCache 是用来做Coroutines+Retrofit缓存的,这个库Readme有点老,下面记录的是我使用的时候踩坑的笔记.

  • 依赖
implementation "com.github.diefferson:CoroutinesCache:0.3.0"
  • 使用
private val coroutinesCacheLY = lazy {
    
    
        CoroutinesCache(
            this,
            byPassCache = false, // false表示从缓存取,true表示从网络获取
            lifecycleOwner = this,
            jsonMapper = MyGsonRetrofitMapper()// 库中自带了GsonRetrofitMapper,后面细说
        )
    }

// 接口
@GET(AUTH_HELP_INFO)
suspend fun authHelpInfo(@QueryMap mData: TreeMap<String, Any>): BResponse<AuthHelpInfo>
// 开始使用缓存请求数据
val result = coroutinesCacheLY.value.asyncCache(
                {
    
     mRepo.authHelpInfo(mParam) },// 请求网络接口获取数据
                "authHelpInfo",// 缓存对应的key
                CachePolicy.TimeCache(20, TimeUnit.MINUTES)// 缓存多长时间
            )
  • MyGsonRetrofitMapper.kt
    最初我用GsonRetrofitMapper类, 结果一直请求网络数据, debug后才发现数据没写进去.
@PublishedApi
internal suspend fun <T> getFromSource(
    source: suspend () -> T,
    key: String,
    isLifecycle: Boolean = false
): T {
    
    
    // 按照实际API从网络请求获取到数据
    val result = source()
    // 再使用Realm将该对象格式化成字符串保存起来 .
    if (jsonMapper.assertValidJson(result)) {
    
    
        database.getDatabase().apply {
    
    
            beginTransaction()
            copyToRealmOrUpdate(
                Cache(
                    key,
                    jsonMapper.toJson(result!!), // jsonMapper就是GsonRetrofitMapper对象, 将对象格式化为字符串保存起来.
                    Calendar.getInstance().time,
                    isLifecycle
                )
            )
            commitTransaction()
            close()
        }
    }
    return result
}

因为当时用GsonRetrofitMapper.assertValidJson()对数据是否可用做判断,导致返回false.然后自定义了MyGsonRetrofitMapper,重写后解决了我的需求:

class MyGsonRetrofitMapper : JsonMapper {
    
    
    override fun toJson(src: Any): String {
    
    
        // 这里是将对象转换为字符串,保存起来.
        val response = src as BResponse<*>
        return Gson().toJson(response, response.javaClass)
    }
    @Throws(JsonSyntaxException::class)
    override fun <T> fromJson(json: String, retrofitResponse: Type): T {
    
    
        // 这里是将字符串格式化为对象返回.
        val reader = StringReader(json)
        val parameterizedType = retrofitResponse as ParameterizedType
        val storedJson = Gson().fromJson(reader, parameterizedType) as Any
        return storedJson as T
    }
    // BResponse是我封装的类
    override fun <T> assertValidJson(result: T): Boolean {
    
    
        if (result is BResponse<*>) {
    
    
            if (result.mException == null) {
    
     //如果返回的对象中没有错误,就返回true,然后使用Realm保存该对象.
                return true
            }
        }
        return false
    }
}

data class BResponse<out T>(
    val mException: Exception? = null,
    val code: String,
    val msg: String,
    val data: T? = null
)

下面解释下如何从缓存中取出对象的

@PublishedApi
internal inline fun <reified T : Any> getFromCacheValidateTime(
    key: String,
    timeCache: CachePolicy.TimeCache
): T? {
    
    
    // 从缓存中取出对象
    val resultDb = database.getDatabase().where(Cache::class.java).equalTo("id", key).findFirst()
    return if (resultDb != null) {
    
    
        if (resultDb.date.isValidCache(timeCache.duration, timeCache.timeUnit)) {
    
    
            val listType = object : TypeToken<T>() {
    
    }.type
            // 这里是将取出的字符串格式化为对象然后返回
            jsonMapper.fromJson(resultDb.data, listType) as T?
        } else {
    
    
            null
        }
    } else {
    
    
        null
    }
}
  • 总结:
    这个库非常容易上手, 还有另外两种模式,缓存同Activity生命周期结合起来,和直接从缓存中取出对象.

猜你喜欢

转载自blog.csdn.net/MoLiao2046/article/details/111299998
今日推荐