LazyColumn 懒加载、items 与 key

源码仓库 :ComposeDemo(分支 main)

技术目标

  1. 理解 懒组合 :可视区域附近的 item 才会进入组合,滚出可视会 dispose (remember 随之清空,除非用 rememberSaveable 等策略)。
  2. 正确使用 items() / itemsIndexed() 与 key ,避免滑动时 状态串行。
  3. 知道 item lambda 的捕获范围 与 参数稳定性(与 07 篇联动)会影响重组范围与跳过行为。

1. DSL 结构

kotlin 复制代码
LazyColumn(
    modifier = ...,
    state = rememberLazyListState(),
) {
    item { /* 单格:头图、间距块、footer */ }
    items(list, key = { it.id }, contentType = { it.type }) { row -> /* 每行 */ }
    // stickyHeader { ... } 等 API 以当前 Material/Compose 版本文档为准
}
  • item { } :不参与 items 的 key 差分,适合静态头尾。
  • items / itemsIndexed :列表差分、动画、状态恢复都依赖 稳定的 key。

2. key 的技术原因

key 给 Compose item 身份 :同一 key 的 item 在列表变化时被视为「同一行」的延续,从而:

  • 保留 remember 状态(如展开、输入中文字)。
  • animateItemPlacement() 等位移动画不会「飞错行」。

常见错误:

做法 后果
错误 key(如随机 uuid 每次变) 每帧重建 item,性能差且状态丢失
仅用 index 作 key 且列表 中间插入/删除 插入点之后所有行的 身份整体漂移 → checkbox 勾选跑到别的行
不同业务实体共用 key 数据覆盖、动画错乱

本仓库 LazyListSampleScreen.kt 使用 DemoRow(id = index, ...) 且 key = { it.id } :在 静态、只追加式 的 demo 数据下等价于 index;真实业务 应使用服务端主键、稳定 uuid 等,而不是「当前列表下标」。


3. Modifier.animateItemPlacement()

启用 item 位移动画时,错误 key 常表现为「飞错行」。排障顺序建议:

  1. 关闭动画,确认数据与 key 是否正确。
  2. 打开动画,观察是否仅 插入/删除 行在动。

4. 性能相关(进阶入口)

  • contentType:不同类型 item(头图 / 文本 / 视频)帮助复用池与测量缓存策略;大列表值得加。
  • 避免在 item lambda 里捕获整个 ViewModel :把展示所需字段拆成 稳定、细粒度 参数传入子 Composable(见 07 篇)。
  • 图片 :大列表解码用 Coil / Glide Compose 等,约束尺寸,避免按原图 decode 撑爆内存。
  • verticalArrangement = spacedBy :本仓库用于 item 间距;注意与 item 内部 padding 的叠加是否符合设计。

5. 仓库路径与代码锚点

LazyListSampleScreen.kt:

  • rows:remember { List(40) { ... } },避免每次重组新建列表引用。
  • items(items = rows, key = { it.id }) { row -> ... }:标准写法模板。

6. 与 Modifier.verticalScroll 的差异(排障)

场景 更适用
少量固定子项、一次全部组合可接受 Column + verticalScroll
大量行、需要视窗懒加载 LazyColumn

同向嵌套(Lazy 里再 Lazy、LazyColumn + verticalScroll)易手势冲突,见 02 篇 nestedScroll 提示。


7. 风险清单

  • 嵌套纵向 LazyColumn:需 明确高度约束 或 nestedScroll 连接。
  • rememberSaveable 保存 LazyListState 与 分页游标 两套真相:恢复滚动位置与重新拉页逻辑要统一,避免「列表顶部但游标在第二页」。
  • 分页追加 时若整表 key 策略变化,可能触发大范围重建;追加页应保持稳定 key 空间。

8. 自检清单

  1. 列表每一项的 key 是否在插入/删除/重排后仍指向同一业务实体?
  2. item 内是否有 大对象捕获 或 非 remember 的昂贵对象创建?
  3. 头尾是否误用 items 导致 多余 key 与差分 ?静态块用 item { }。
  4. 图片与异步内容是否有 尺寸约束与取消(滚出视窗不再加载)?

系列推荐

《副作用 API:LaunchedEffect、DisposableEffect、SideEffect》

《Modifier 链与顺序、测量与命中区域》

相关推荐
Android-Flutter7 小时前
Compose 管理状态 详解
android·compose
缓慢更新8 小时前
审批的加签与会签:多人意见怎么合
android·java·数据库·低代码·rxjava
我怀里的猫9 小时前
android-activity-launch-sequence
android
YB137511 小时前
Jetpack Compose 动画rememberInfiniteTransition
android
baidu_2474386114 小时前
Android 自定义竖直的虚线
android
程序员老刘14 小时前
Flutter版本选择指南:3.44稳定了11周正式转正 | 2026年10月
flutter·ai编程·客户端
传奇开心果编程14 小时前
【Jetpack Compose娓娓道来】 第25课:ViewModel就是UI界面的大脑
android·kotlin·移动开发·jetpack compose·编程语言理论·编程框架·声明式ui
马立杰15 小时前
PHP 未授权 RCE 应急响应:CVE-2026-109618 CVE-2026-109619 排查与加固实战
android·开发语言·php
NamoAmitabha12815 小时前
安装“编译器环境”(Android Studio)--deepseek--Cocos --Creator3.8.8
android·ide·android studio
聚美智数15 小时前
文档转换 API‑文档转 PDF‑PDF 转文档‑异步文档处理‑文件格式迁移‑转换结果回调推送 API 接口介绍
android·java·pdf