1、什么是 Jetpack Compose?
Jetpack Compose 是 Google 推出的现代 Android UI 开发工具包(Toolkit),于 2021 年正式稳定发布,到 2026 年已成为 Android UI 开发的首选标准。它完全使用 Kotlin 代码以声明式方式构建原生 UI,无需 XML 布局文件、findViewById 等传统 View 系统操作。
Compose 的核心理念是声明式 UI(Declarative UI)。开发者只需描述“UI 在当前状态下应该是什么样子”,框架会自动处理“如何更新界面”。这与传统命令式(Imperative)UI 形成鲜明对比,后者需要手动操作视图树、更新属性、管理状态同步。
简单示例(Hello World):
@Composable
fun Greeting(name: String) {
Text(
text = "Hello, $name!",
style = MaterialTheme.typography.headlineMedium
)
}
@Composable
fun MyApp() {
Greeting("Android Compose")
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
只需几行代码即可渲染界面,且支持实时预览(@Preview)。Compose 内置 Material Design 3 支持、响应式布局、动画等现代特性,已广泛用于 Google 自家应用,并支持 Compose Multiplatform 跨平台开发。
2、声明式 UI 编程 vs 传统命令式 UI
传统 View 系统(XML + Kotlin/Java) 是命令式的:
- 在 XML 中定义静态布局。
- 通过 findViewById 获取视图引用。
- 用户交互或数据变化时,手动调用 setText()、setVisibility()、addView() 等方法更新 UI。
- 需要处理生命周期、视图复用(RecyclerView Adapter)、状态一致性等问题,容易产生 bug(如忘记更新某个视图导致 UI 不一致)。
Compose 的声明式编程:
- UI 是纯函数的输出:输入相同状态 → 输出相同 UI 描述。
- 状态变化时,框架自动重新执行相关 Composable 函数(Recomposition),智能更新界面。
- 无需手动管理视图树,代码更简洁、可组合、可复用。
声明式 UI 的优势体现在:
- 状态驱动:UI 是状态的纯映射,数据变 → UI 自动变。
- 减少 boilerplate:无需 XML、Adapter 大量模板代码。
- 更好的可维护性:UI 逻辑与数据逻辑分离,易于测试和重构。
3、Compose 为什么比传统 UI 开发效率更高?
大量实际案例和开发者反馈显示,Compose 显著提升生产力:
- 代码量大幅减少:同一界面,Compose 代码量通常只有 XML + Kotlin 的 40-60%。无需切换文件(XML/Kotlin),所有逻辑在同一 Kotlin 文件中。
- 实时预览与迭代快:@Preview 支持参数化预览、暗黑模式、多设备预览,几乎即时更新,极大加速 UI 调优。
- 可组合性强:自定义组件就是普通 @Composable 函数,支持参数传递、Slot API(类似内容槽),复用极高。传统自定义 View 需要复杂继承和测量逻辑。
- 状态管理简化:mutableStateOf + remember 结合 ViewModel + Flow,单向数据流自然实现。无需手动绑定监听器。
- 动画与交互:内置强大动画 API(如 animate*AsState、updateTransition),手势处理更直观。
- 测试友好:Composable 可单元测试,无需 Instrumentation 测试。
- 性能与适配:智能重组(Targeted Recomposition)+ Lazy 组件,在动态 UI 上表现优秀。2026 年版本进一步优化了性能、适配大屏/折叠屏。
实际数据:Play Store 团队反馈 UI 代码减少约 50%,开发速度显著提升。许多团队迁移后表示“再也不想回 XML 了”。
当然,传统 View 在极致性能优化或遗留项目中仍有价值,但新项目强烈推荐 Compose。
4、Compose 的本质原理:Compiler + Runtime + UI
Compose 不是简单的 UI 库,而是由三部分组成:Compiler(编译器插件)、Runtime(运行时) 和 UI 层。
- Composable 函数与 Compiler 的魔法
所有 UI 构建函数必须标注 @Composable。Compose Compiler 插件(Kotlin Compiler Plugin)在编译时对这些函数进行代码转换(IR 变换):
- 跟踪函数调用位置和执行顺序。
- 插入“记住”机制(remember),支持跨重组持久化状态。
- 生成元数据,用于运行时追踪依赖。
Composable 函数必须满足:
- 幂等(Idempotent):相同输入产生相同输出。
- 无副作用:不要在函数体内直接修改共享状态、网络请求等(应通过回调或 SideEffect 处理)。
- 快速执行:避免耗时操作。
- 状态与 Recomposition(重组)
状态是核心,通常用 mutableStateOf 创建可观察状态:
Kotlin
var count by remember { mutableIntStateOf(0) }
remember 确保状态在重组时不丢失。状态变化会标记相关 Composable 为“无效”,触发 Recomposition。
Recomposition 不是全量重绘:
- Compose 只重新执行依赖变化数据的 Composable 子树。
- 这依赖于 Slot Table 数据结构。
- Slot Table:Compose 的核心内存结构
Slot Table 是 Compose Runtime 使用的扁平化数据结构(类似 Gap Buffer),用于记录 Composition(组合)过程:
- 记录每个 Composable 的调用顺序、组(Group)信息、Remembered 值、状态读取记录。
- 像“笔记本”一样,记录“上次执行了什么、读了哪些状态”。
- 状态变化时,Runtime 遍历 Slot Table,标记无效组,只重新执行必要部分。
- 支持高效插入/删除(条件 UI 如 if-else)、O(1) 操作,避免传统树 Diff 的开销。
Gap Buffer 允许在列表中间高效插入/删除组,实现动态 UI(如 LazyColumn)的高性能。
重组流程(简化):
初始 Composition:执行 Composable,构建 Slot Table 和 UI 节点树。
状态变化:通知 Runtime。
Recomposition:只执行无效的 Composable,更新 Slot Table 和渲染。
应用变更:最小化更新到实际显示(Applier)。
这使得 Compose 能保持高帧率(60/120fps),即使复杂界面也能高效响应。
- 其他关键机制
- Stability:稳定类型(如 immutable data class、primitive)允许编译器跳过不必要的重组检查。
- Phases:Composition → Layout → Drawing 等阶段,开发者可通过 remember、LaunchedEffect 等精确控制。
- CompositionLocal:隐式传递主题、配置等数据。
5、代码示例详解
示例 1:基础计数器(状态管理)
@Composable
fun CounterScreen() {
var count by remember { mutableIntStateOf(0) } // rememberSaveable 可跨配置变更保存
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "计数: $count",
style = MaterialTheme.typography.headlineLarge
)
Spacer(modifier = Modifier.height(16.dp))
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = { count-- }) {
Text("-")
}
Button(onClick = { count++ }) {
Text("+")
}
Button(onClick = { count = 0 }) {
Text("重置")
}
}
}
}
原理:count 变化触发包含它的 Composable 重组,Text 自动更新。其他无关部分跳过。
示例 2:列表(LazyColumn + 高效重组)
@Composable
fun TodoList(todos: List<TodoItem>, onToggle: (Int) -> Unit) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(16.dp)
) {
items(
items = todos,
key = { it.id } // 关键:稳定 key 优化重组
) { todo ->
TodoItemRow(
todo = todo,
onToggle = { onToggle(todo.id) }
)
}
}
}
@Composable
private fun TodoItemRow(todo: TodoItem, onToggle: () -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
.clickable(onClick = onToggle),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
checked = todo.isDone,
onCheckedChange = { onToggle() }
)
Text(
text = todo.title,
modifier = Modifier.padding(start = 8.dp),
style = if (todo.isDone) MaterialTheme.typography.bodyMedium.copy(textDecoration = TextDecoration.LineThrough)
else MaterialTheme.typography.bodyLarge
)
}
}
items + key 确保只有变化项重组,类似 RecyclerView 但更简洁。
示例 3:副作用与异步(LaunchedEffect)
@Composable
fun SearchScreen(viewModel: SearchViewModel = viewModel()) {
val query by viewModel.query.collectAsState()
val results by viewModel.results.collectAsState()
LaunchedEffect(query) { // query 变化时执行
if (query.length > 2) {
viewModel.search(query)
}
}
}
LaunchedEffect 在 Composition 中启动协程,键变化时取消重启,避免内存泄漏。
示例 4:自定义 Modifier 与动画
fun Modifier.bounceClick() = composed {
var scale by remember { mutableFloatStateOf(1f) }
val animatedScale by animateFloatAsState(scale)
this .scale(animatedScale)
.pointerInput(Unit) {
detectTapGestures(
onPress = {
scale = 0.95f
tryAwaitRelease()
scale = 1f
}
)
}
}
Compose 让自定义行为像链式调用一样简单。
6、性能优化与最佳实践
- 提升稳定性:使用 immutable 数据、@Stable 注解。
- 避免高频重组:状态下移(把状态放在需要它的最小 Composable 中)、使用 derivedStateOf。
- Lazy 组件:优先使用 LazyColumn/LazyRow/Grid。
- 工具:Layout Inspector、Recomposition Highlighter(Android Studio)。
- 2026 年更新:更好的大屏适配、动画调试工具、性能改进。
7、总结与展望
Jetpack Compose 通过声明式范式、Compiler 智能变换和 Slot Table 高效运行时,彻底改变了 Android UI 开发方式。它让开发者聚焦业务逻辑而非 UI 细节,代码更少、迭代更快、维护更容易、性能更优。
到 2026 年,它已是成熟、生产就绪的标准,强烈建议所有新项目采用,并逐步迁移遗留代码。