You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在JVM Kotlin中实现类似Android Compose remember的键控懒加载功能

纯JVM Kotlin实现类似Compose的remember(key) { init }功能

Kotlin标准库并没有提供这种带键值校验的懒加载机制,需要自定义实现。

这种需求的核心是:每次访问属性时,先获取当前键值,若键值与上次记录的不同,则重新执行初始化逻辑生成新值;若键值未变,则直接返回缓存的旧值——和Lazy的区别在于它不是仅初始化一次,而是会根据键值变化触发重新初始化。

自定义实现示例

可以通过委托属性来实现这个功能,以下是一个基础版本:

class Remember<K, V>(
    private val keyProvider: () -> K,
    private val init: () -> V
) {
    private var currentKey: K? = null
    private var currentValue: V? = null

    operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): V {
        val newKey = keyProvider()
        if (currentKey != newKey) {
            currentValue = init()
            currentKey = newKey
        }
        return currentValue!!
    }
}

// 扩展函数简化调用
fun <K, V> remember(keyProvider: () -> K, init: () -> V): Remember<K, V> {
    return Remember(keyProvider, init)
}

使用方式

var counter = 0

// 用remember委托属性,键为counter的值
val rememberedValue by remember(keyProvider = { counter }) {
    println("重新计算值")
    counter * 2
}

fun main() {
    println(rememberedValue) // 输出:重新计算值\n0
    counter = 5
    println(rememberedValue) // 输出:重新计算值\n10
    println(rememberedValue) // 输出:10(不触发重新计算)
}

线程安全优化

如果需要在多线程环境下使用,可以给getValue方法添加同步锁,避免并发问题:

operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): V {
    synchronized(this) {
        val newKey = keyProvider()
        if (currentKey != newKey) {
            currentValue = init()
            currentKey = newKey
        }
        return currentValue!!
    }
}

注意事项

  • 键的相等性判断依赖==运算符,若使用自定义类型作为键,需要确保正确实现equals()和hashCode()方法,避免误判。
  • 初始化逻辑init可能会抛出异常,使用时需要自行处理异常场景。

内容的提问来源于stack exchange,提问作者askSoap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:43:13