编程思想
Jetpack Compose 是一个声明式 UI 框架。要用好它,需要从根本上转变看待 UI 的方式:从“修改视图”转变为“描述视图”。
声明式 vs 命令式
核心差异
- 命令式 (Imperative): 告诉机器“怎么做”。例如:
nameView.setText("Virogu")。 - 声明式 (Declarative): 告诉机器“是什么”。例如:
Text(text = "Virogu")。
核心思维模型
1. UI 是状态的函数
在 Compose 中,UI 是不可变的,无法在创建后进行更新。触发 UI 更新的唯一方式是改变状态 (State)。
公式
$$ UI = f(State) $$ 当 $State$ 发生变化时,函数 $f$ 重新运行,产生新的 $UI$。
2. 重组 (Recomposition)
当状态更新时,Compose 会再次调用可组合函数。这个过程称为重组。
重组的五个特性(点击展开)
- 可组合函数可以按任何顺序执行:不要依赖上一个函数的执行结果。
- 可组合函数可以并行运行:Compose 会通过在多个线程上运行可组合函数来利用多核。
- 重组会跳过尽可能多的内容:如果参数没变,Compose 会智能跳过该函数的重组。
- 重组是乐观的操作:Compose 预计在参数再次更改之前完成重组。如果参数在完成之前更改,Compose 可能会取消重组并以新参数重新开始。
- 可组合函数可能会非常频繁地运行:例如在动画期间,每帧都会运行。
3. 单向数据流 (UDF)
单向数据流是一种设计模式,状态向下流动,事件向上流动。
kotlin
@Composable
fun Counter(count: Int, onIncrement: () -> Unit) {
Column {
Text("Count: $count") // 状态向下流动
Button(onClick = onIncrement) { // 事件向上流动
Text("Increment")
}
}
}kotlin
@Composable
fun BadCounter() {
var count = 0 // 这样定义变量重组时会重置
Button(onClick = { count++ }) { // 事件直接修改局部变量,无法触发更新
Text("Increment: $count")
}
}