Jetpack Compose 像React或者Flutter一样,需要通过state变更驱动UI刷新。但是Compose没有React的ClassComponent
或者Flutter的StatefulWidget
,那Compose是如何更新并监视state呢?
state
一种方式是使用state{...}
方法声明初始状态,并监听状态变化。
当状态变化时,会触发recomposition
执行从而刷新UI
@Composable
fun MyCheckbox() {
// 初始state
var checked by state { false }
Checkbox(
checked = checked.value,
onCheckedChange = {
// 更新state后,recomposition执行
checked.value = it
}
)
}
state{...}
返回checked
的同时,建立当前节点(MyCheckbox)对state的监听
state{...}
并不直接返回bool值,而是一个代理:
interface MutableState<T> : State<T> {
override var value: T
operator fun component1(): T
operator fun component2(): (T) -> Unit
operator fun getValue(thisObj: Any?, property: KProperty<*>): T
operator fun setValue(thisObj: Any?, property: KProperty<*>, next: T)
}
当checked被set时,通过代理触发recomposition
,找到observer的节点(MyCheckbox)并重新执行Composable方法。
可以看到,Compose中吸收了类似Reat Hooks的机制,让函数组件依然可以像类组件一样管理和订阅state。
model
第二种方法是使用@model
注解,使用@modle
添加的Class,其所有的的属性的变成了可观察的状态
@Model
class Count(
var count: Int = 0
)
@Composable
fun MyText() {
// 使用Modle类创建实例
val count = Count()
Ripple(bounded = false) {
Clickable(onClick = {
// 更新Model的值,recomposition执行
count.count += 1
}) {
Container {
// count中保存Model的最新值
Text(text = count.count.toString())
}
}
}
}
@model
在使用上更像是state{}的语法糖,写起来更简洁