LazyColumn 懒加载、items 与 key

源码仓库ComposeDemo(分支 main

技术目标

  1. 理解 懒组合 :可视区域附近的 item 才会进入组合,滚出可视会 disposeremember 随之清空,除非用 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 { } :不参与 itemskey 差分,适合静态头尾。
  • 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

  • rowsremember { 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 链与顺序、测量与命中区域》

相关推荐
ZZZMMM.zip2 小时前
基于鸿蒙HarmonyOS NEXT开发AI英语口语应用:智能口语练习新体验与鸿蒙Flutter框架跨端实
人工智能·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
心中有国也有家2 小时前
AtomGit Flutter 鸿蒙客户端:白噪音场景的视觉设计
学习·flutter·华为·harmonyos
心中有国也有家3 小时前
AtomGit Flutter 鸿蒙客户端:呼吸练习的完整生命周期
学习·flutter·华为·harmonyos
星空语4 小时前
音频001_Android+Linux车载/手机音频全链路分层架构图
android·linux·音视频
CyL_Cly4 小时前
解决官网下载慢!Android Studio 最新版网盘下载
android·ide·android studio
智塑未来4 小时前
鸿蒙系统对比安卓、iOS,核心优势是什么?
android·ios·harmonyos
AI刀刀4 小时前
豆包智能体对话导出后,如何构建长期归档与高效检索体系?
android·人工智能·word·excel·ai导出鸭
心中有国也有家5 小时前
AtomGit Flutter 鸿蒙客户端:呼吸球动画
学习·flutter·华为·harmonyos
初雪云6 小时前
iOS 上架入门:证书、描述文件、IPA 上传到底是什么关系?
android·ios·自动化·产品经理·iphone
心中有国也有家7 小时前
AtomGit Flutter 鸿蒙客户端:呼吸练习的三种科学模式
学习·flutter·华为·harmonyos