Kotlin Observable使用疑问:参数传递及代码方案优劣判断
Kotlin Observable 委托相关问题解答
嘿,针对你提出的两个Kotlin Observable委托相关问题,我来详细拆解解答:
问题1:在Kotlin中使用Observable时,是否需要将newValue作为参数传入函数?
首先得明确:Delegates.observable的回调lambda是必须遵循固定参数签名的——它要求接收三个参数:property(对应属性的KProperty对象)、oldValue(修改前的属性值)、newValue(修改后的属性值),这是由它的函数定义决定的:
fun <T> observable(initialValue: T, onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit): ReadWriteProperty<Any?, T>
不过,如果你在回调逻辑里用不到某个参数,可以用下划线_来忽略它,比如不需要property和oldValue的话,可以写成:
private var allList by Delegates.observable(listOf<MSetting>()) { _, _, newValue -> btnRestore.isEnabled = newValue.size >= 1 }
那回到你的问题:如果你的业务逻辑需要用到修改后的新值(比如判断列表长度来控制按钮状态),那肯定要把newValue传入你要封装的函数里;如果逻辑完全不需要这个值,那可以用下划线占位忽略,但lambda的参数位置还是得保留哦。
问题2:封装Code A为函数,Code B与Code C哪个正确?哪个更优?
先补全一下合理的Code B和Code C场景(因为你提供的Code B不完整,我根据日常开发的封装习惯推测了两种常见写法):
原始Code A:
private var allList by Delegates.observable(listOf<MSetting>()) { property, oldValue, newValue -> btnRestore.isEnabled = newValue.size >= 1 }
推测的Code B(将逻辑封装为带参数的独立函数):
private var allList by Delegates.observable(listOf<MSetting>()) { _, _, newValue -> updateBtnRestoreState(newValue) } private fun updateBtnRestoreState(newList: List<MSetting>) { btnRestore.isEnabled = newList.size >= 1 }
推测的Code C(不传入newValue,直接访问私有变量allList):
private var allList by Delegates.observable(listOf<MSetting>()) { _, _, _ -> updateBtnRestoreState() } private fun updateBtnRestoreState() { btnRestore.isEnabled = allList.size >= 1 }
正确性判断:
两种写法在大多数单线程场景下都能正常运行,但背后的逻辑有本质区别:
- Code B直接使用回调提供的
newValue作为函数参数,这个值是确定的——就是触发本次回调的属性修改后的结果,不会受后续可能的属性修改影响。 - Code C通过直接访问私有变量
allList来获取值,虽然单线程下没问题,但如果是多线程环境,回调执行过程中allList可能被再次修改,此时函数拿到的就不是触发本次回调的那个值了,会出现逻辑偏差。
优劣对比:
毫无疑问Code B更优,理由如下:
- 语义清晰,可读性强:函数
updateBtnRestoreState的参数明确告诉阅读者,它依赖一个列表状态来更新按钮,逻辑一目了然。 - 避免潜在的并发问题:如刚才所说,多线程场景下Code C可能拿到非预期的值,而Code B使用回调提供的
newValue,完全不受后续修改影响,逻辑更可靠。 - 耦合度更低,复用性更好:Code B的函数不依赖
allList这个私有变量,其他地方需要更新按钮状态时,只要传入任意列表就能调用,复用性拉满;而Code C的函数完全绑定在allList上,无法单独复用。
内容的提问来源于stack exchange,提问作者HelloCW
相关产品推荐
相关产品推荐

