Android 开发手册ANDROID DEV

CHAPTER 03声明式 UI · DECLARATIVE

Jetpack
Compose

用声明"界面应该是什么样"取代命令式"一步步改界面"。状态驱动重组,界面是状态的函数。

开始阅读难度进阶约3小时
03.1

声明式心智模型

传统 View 是"拿到 TextView 设置文字";Compose 是"如果 count 是 5 就显示 5"。状态变化时框架重组(recompose)受影响的 UI。

重组是廉价的

Compose 只重组真正读取了变化状态的组件,而非整棵视图树。保持可组合函数无副作用、幂等,是性能关键。

03.2

可组合函数

@Composable 注解标记 UI 函数,返回 Unit,通过组合子组件构建界面。

@Composable
fun Greeting(name: String) {
    Column {
        Text("欢迎", style = MaterialTheme.typography.titleLarge)
        Text(name, color = MaterialTheme.colorScheme.primary)
    }
}
03.3

状态与重组

remember 跨重组保存值,mutableStateOf 包裹可变状态。读它的组件会在其变化时重组。

@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }
    Button(onClick = { count++ }) {
        Text("点击了 $count 次")        // count 变化自动重组
    }
}
// 来自 VM 的状态:val count by viewModel.count.collectAsState()
状态提升

把可变状态提升到调用方,子组件通过回调上报事件,保持子组件无状态可复用——这是 Compose 的核心模式。

03.4

Modifier

Modifier 链式描述尺寸、边距、背景、点击等。顺序有意义:先写的先应用。

Text("Hi", modifier = Modifier
    .padding(16.dp)
    .fillMaxWidth()
    .background(Color.LightGray)
    .clickable { /* 点击 */ })
03.5

布局

Column(纵向)/ Row(横向)/ Box(堆叠)对应线性布局,LazyColumn 对应滚动列表。

Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
    Text("标题"); Button(onClick = {}) { Text("确认") }
}
03.6

列表

LazyColumn 按需组合可见项,是 RecyclerView 的声明式等价物。

LazyColumn {
    items(users, key = { it.id }) { user ->
        UserRow(user)         // key 保证稳定重组
    }
}
03.7

导航

Navigation Compose 用 NavHost 定义路由,navController.navigate 切换页面。

NavHost(navController, startDestination = "list") {
    composable("list") { ListScreen(navController) }
    composable("detail/{id}") { DetailScreen(it.arguments?.getString("id")) }
}
03.8

常见陷阱

为什么状态变了界面没刷新?

多半是用了普通 var 而非 mutableStateOf,或没用 remember 导致重组后值被重置。确保可观察状态由 Compose 运行时托管。

重组里能发起网络请求吗?

不应在可组合函数体里做副作用(重组可能多次)。用 LaunchedEffect/DisposableEffect 在正确生命周期触发一次性副作用。

03.9

实战练习

延伸资源