Kotlin get set函数
拆解下面这个set函数
@Volatile
private var mScreenActionIsWakeUp = true
set(value) {
val lastWakeup = field
field = value
mScreenFadeAnimator.animateTo(lastWakeup, value)
}逐层拆解:
- @Volatile — 可见性保证
等价于 Java 的 volatile 关键字:
- 保证多线程间对该变量的读写可见性(禁止 CPU 缓存/指令重排优化)
- 这里因为主线程写、ScreenFade 线程读,需要跨线程可见
- private var mScreenActionIsWakeUp = true — 属性声明

- set(value) { … } — 自定义 setter
这是 Kotlin 属性访问器(Property Accessor) 语法。Kotlin 的 var 属性本质上会生成:
- 一个 backing field(幕后字段)
- 一个 get() 方法(这里用默认的)
- 一个 set() 方法(这里自定义了)
任何对该属性的赋值操作都会走这个 setter,而不是直接写字段。
- field — 幕后字段关键字
field 是 Kotlin 特有的关键字,只能在 getter/setter 内部使用,代表属性的实际存储值。
set(value) {
val lastWakeup = field // ① 读取当前旧值(赋值前的值)
field = value // ② 将新值写入幕后字段
mScreenFadeAnimator.animateTo(lastWakeup, value) // ③ 用旧值和新值触发动画
}为什么不能写 this.mScreenActionIsWakeUp 代替 field?因为那会递归调用 setter 自身,导致栈溢出。field 是直接操作底层字段的唯一方式。
-
等价的 Java 代码
@Volatile
private volatile boolean mScreenActionIsWakeUp = true;
// 编译器不会真的生成这个方法,但语义等价:
private void setMScreenActionIsWakeUp(boolean value) {
boolean lastWakeup = this.mScreenActionIsWakeUp; // field → 直接读字段
this.mScreenActionIsWakeUp = value; // field = value → 直接写字段
mScreenFadeAnimator.animateTo(lastWakeup, value);
}- 触发时机
在 updateScreenFadeState 中:
private fun updateScreenFadeState(wakeup: Boolean) {
mScreenFadeHandler?.post {
mScreenActionIsWakeUp = wakeup // ← 赋值就会触发自定义 setter
}
}这行赋值不是简单的写字段,而是执行了:
- 保存旧状态(上一次是亮屏还是灭屏)
- 更新为新状态
- 调用 animateTo(旧状态, 新状态) 启动弹簧动画
设计意图
把状态变更和动画触发绑定在一起,确保只要状态改变就一定会启动动画,不可能出现”改了状态忘了触发动画”的情况。这 是一种观察者模式的轻量实现——属性自身就是被观察的对象。