在 Jetpack Compose 中,Column 和 LazyColumn 都用于垂直排列子项,但它们的渲染策略完全不同。
| 特性 | Column | LazyColumn |
|---|---|---|
| 📦 渲染方式 | 一次性渲染所有子项 | 仅渲染可见项 + 预取 |
| ⚡ 性能表现 | 适合少量固定元素 ( < 20 ) | 千级列表流畅,按需合成 |
| ♻️ 回收复用 | 无回收,全部保持活跃 | 自动回收/复用 item 组件 |
| 🧠 内存占用 | 随子项数量线性增长 | 几乎恒定 (仅可见区域) |
| 📜 滚动支持 | 需嵌套 scrollable | 内置滚动、惯性、fling |
| 🎯 适用场景 | 表单、设置页、固定布局 | 聊天记录、Feed、长列表 |
想象一个包含 10,000 条消息的聊天界面 —— 如果使用 Column,Compose 会尝试一次性测量、布局并绘制所有 item,导致:
LazyColumn 通过延迟组合 + 项缓存,只合成可见区域附近的 item,滚动时复用组件,让列表丝滑流畅。
以下代码展示了一个带 items 的典型 LazyColumn,包含 100 个文本项:
@Composable
fun SimpleLazyList() {
val list = (1..100).toList()
LazyColumn(
modifier = Modifier.padding(8.dp),
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp)
) {
items(list) { index ->
ListItemCard(index = index)
}
}
}
@Composable
fun ListItemCard(index: Int) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
colors = CardDefaults.cardColors(
containerColor = Color(0xFFF7E5C2)
),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Text(
text = "列表项 #$index",
modifier = Modifier.padding(16.dp),
style = MaterialTheme.typography.bodyLarge
)
}
}
使用 itemsIndexed 或 items 结合 key 提升复用效率:
@Composable
fun MessageList(messages: List<Message>) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
itemsIndexed(
items = messages,
key = { _, msg -> msg.id } // 稳定 key 避免不必要的重组
) { index, message ->
MessageRow(message, index)
}
}
}
✨ 核心要点