在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
相关产品推荐
相关产品推荐

