@Composable 是 Jetpack Compose 的“魔法标记”。它告诉编译器:这个函数会发射 UI 或 描述界面结构。没有它,Compose 无法识别你的可组合项。
@Composable
fun Greeting(name: String) {
Text(text = "你好, $name!")
}
注解让 Compose 编译器能够追踪函数调用,并为后续的重组提供插桩。
Compose 运行时对可组合函数有明确的约定,遵守规则才能保证正确、高效地渲染。
| 规则 | 说明 | 示例 / 反例 |
|---|---|---|
| 幂等 & 无副作用 | 相同输入应产生相同输出,不修改外部状态 | ❌ 在可组合内写 var count = 0 |
| 不依赖执行顺序 | 可组合可能在任何顺序下执行(并行预览) | ✅ 只依赖参数和 Composable 作用域 |
| 快速 & 无阻塞 | 不要执行耗时操作、网络请求或复杂计算 | ✅ 使用 LaunchedEffect 处理副作用 |
| 读取状态需重组 | 通过 State / MutableState 读取,触发重组 | ✅ val count by remember { mutableStateOf(0) } |
| 可组合函数可以多次执行 | 重组时会重新调用,不要假设只执行一次 | ✅ 用 remember 缓存昂贵对象 |
💡 黄金法则:可组合函数只描述 UI,所有“副作用”都交给 LaunchedEffect / DisposableEffect 等作用域。
重组:当状态变化时,Compose 重新执行受影响的可组合函数以更新 UI。
智能重组:Compose 编译器通过静态分析,只重组读取了变化状态的代码块,跳过未读取的部分,极大提升性能。
count++@Composable
fun CounterExample() {
var count by remember { mutableStateOf(0) }
val logo = remember { /* 昂贵计算 */ }
Column {
// 只有这个 Text 读取 count → 重组时仅它重新执行
Text("点击次数: $count")
// 未读取 count → 智能重组跳过
Image(bitmap = logo, contentDescription = "Logo")
Button(onClick = { count++ }) {
Text("增加")
}
}
}
🔍 点击按钮后,Text("点击次数: $count") 重组,Image 和 Button 的 content 不会重新执行,这就是智能重组的威力。
viewModel() 配合 StateFlow / collectAsState() 实现稳定的状态管理,重组只发生在 collect 读取处。