Kotlin 属性委托 observable 的实现原理

Kotlin 的 Delegates.observable 是 Kotlin 标准库中提供的一个属性委托,它允许你在属性的值发生变化时自动执行某段逻辑,比如常用于监听属性变化(例如 UI 数据更新)。

🔧 基本使用示例:

1
2
3
4
5
6
7
8
9
10
import kotlin.properties.Delegates

var name: String by Delegates.observable("initial") { property, oldValue, newValue ->
println("${property.name} changed from $oldValue to $newValue")
}

fun main() {
name = "Alice"
name = "Bob"
}

输出:

1
2
name changed from initial to Alice
name changed from Alice to Bob

⚙️ 实现原理

✅ 1. Delegates.observable(...) 返回了一个实现了 ReadWriteProperty 接口的对象:

1
2
3
4
5
public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
ReadWriteProperty<Any?, T> =
object : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
}

它返回了一个 ObservableProperty 实例。


✅ 2. ObservableProperty 实现了属性委托接口ReadWriteProperty

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class ObservableProperty<V>(initialValue: V) : ReadWriteProperty<Any?, V> {
private var value = initialValue

protected open fun beforeChange(property: KProperty<*>, oldValue: V, newValue: V): Boolean = true

protected open fun afterChange(property: KProperty<*>, oldValue: V, newValue: V): Unit {}

public override fun getValue(thisRef: Any?, property: KProperty<*>): V {
return value
}

public override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
val oldValue = this.value
if (!beforeChange(property, oldValue, value)) {
return
}
this.value = value
afterChange(property, oldValue, value)
}

override fun toString(): String = "ObservableProperty(value=$value)"
}

beforeChange在属性值被变更前被调用,默认返回true,就是说即使你写出这样的代码:

1
2
3
4
5
6
7
8
9
10
import kotlin.properties.Delegates

var name: String by Delegates.observable("init") { property, oldValue, newValue ->
println("${property.name} changed from $oldValue to $newValue")
}

fun main() {
name = "init"
name = "Bob"
}

也会输出结果:

1
2
name changed from init to init
name changed from init to Bob

ObservableProperty内部维护了属性值,并在 setValue 方法中触发回调,这个回调的实现就是我们传入的lambda参数onChange

每次我们通过赋值等操作修改被委托的属性时,都会触发 setValue() 方法,从而调用 onChange 回调。


📌 总结:工作机制

步骤 动作
1️⃣ Delegates.observable(initialValue, onChange) 返回 ObservableProperty 实例
2️⃣ ObservableProperty 实现了 ReadWriteProperty 接口
3️⃣ Kotlin 编译器在 by 后会将属性访问转发给 getValue()setValue()
4️⃣ setValue() 中自动触发 onChange() 回调

💡 使用场景

  • 数据绑定(如 UI)
  • 表单输入监听
  • MVVM 架构中 ViewModel 属性监听
  • 日志审计、调试属性变化等