0

我有很多看起来像这样的方法:

override suspend fun getBalance(): Result<BigDecimal> = withContext(Dispatchers.IO) {
    Log.d(TAG, "Fetching balance from data store")
    val balance = balancePreferencesFlow.firstOrNull()
        ?: return@withContext Result.Error(CacheIsInvalidException)

    return@withContext when (balance) {
        is Result.Success -> {
            if ((balance.data.timestamp + ttl) <= getCurrentTime()) {
                deleteBalance()
                Result.Error(CacheIsInvalidException)
            } else {
                resultOf { balance.data.toDomainType() }
            }
        }
        is Result.Error -> balance
    }
}

在那里我从 DataStore 收集某种类型的流,然后如果它是成功结果(带有类型 T 的数据参数),我应该得到它的时间戳(它是一个数据类字段),如果条件为真,则删除无效数据,如果为假,则返回转换后的结果。

转换函数看起来像这样:

fun BigDecimal.toPersistenceType(): Balance = Balance(
    balanceAmount = this,
    timestamp = getCurrentTime()
)

fun Balance.toDomainType(): BigDecimal = this.balanceAmount

我试图以这种方式制作一个抽象方法,但我不完全理解我应该如何将 lambda 传递给它。

suspend inline fun <reified T : Any, reified V : Any> getPreferencesDataStoreCache(
    preferencesFlow: Flow<Result<V>>,
    ttl: Long,
    deleteCachedData: () -> Unit,
    getTimestamp: () -> Long,
    convertData: () -> T
): Result<T> {
    val preferencesResult = preferencesFlow.firstOrNull()

    return when (preferencesResult) {
        is Result.Success -> {
            if ((getTimestamp() + ttl) <= getCurrentTime()) {
                deleteCachedData()
                Result.Error(CacheIsInvalidException)
            } else {
                resultOf { preferencesResult.data.convertData() }
            }
        }
        is Result.Error -> preferencesResult
        else -> Result.Error(CacheIsInvalidException)
    }
}

用于转换的 lambda 应该看起来像一个扩展方法。

结果类:

sealed class Result<out T : Any> {

    data class Success<out Type : Any>(val data: Type) : Result<Type>()
    data class Error(val exception: Exception) : Result<Nothing>()
}
4

1 回答 1

0

首先,我在这里看到了一些缓存工作,从我的观点来看,这些工作应该放在一个界面中。

interface Cache {
    val timestamp: Long
    fun clear()
}

如果您的缓存仍然为空,您可以使timestamp属性为空以返回- 这取决于您。null

然后你需要的通用方法我假设放在Result类中,因为它似乎只是它自己的工作。

sealed class Result<out T : Any> {
    data class Success<out Type : Any>(val data: Type) : Result<Type>()
    data class Error(val exception: Exception) : Result<Nothing>()

    fun <R : Any> convertIfValid(cache: Cache, ttl: Long, converter: (T) -> R) : Result<R> =
            when (this) {
                is Success -> {
                    if (cache.timestamp + ttl <= getCurrentTime()) {
                        cache.clear()
                        Error(CacheIsInvalidException())
                    } else {
                        Success(converter(data))
                    }
                }
                is Error -> this
            }
}

将方法也放在一些注入的实体中可能会更好getCurrentTime,但这在这篇文章中并不重要。顺便说一句,正如您在此处看到的那样,when我没有放置else状态,因为密封类没有必要。

从您的代码中,我可以制作一个仅用于平衡的缓存实现示例:

class BalanceCache : Cache {
    var balanceValue = Balance()
    override val timestamp: Long
        get() = balanceValue.timestamp

    override fun clear() {
        deleteBalance()
    }
}

如果您需要我提供更多示例,请向我提供有关您想要使用它的代码的更多详细信息。

于 2020-12-09T08:11:28.230 回答