【鸿蒙心迹】长列表性能优化实录:LazyForEach、组件复用与滑动丝滑的工程化
前言
数据进了数据库,列表就成了第一个性能战场。待办攒到几百条之后,码上清单的滑动开始"有点粘"——不是卡死,是那种说不清的滞涩。这篇把排查和优化的完整过程记录下来,核心就一句话:把"感觉不丝滑"变成帧率数据,再让每一帧的账都对得上。
一、先定量,再动手
Profiler 那篇立过规矩:性能问题先看数据。Frame 轨道采一段滑动,结论很清楚:平滑帧 4~5ms 轻松跑,但每隔几屏冒出一串超时帧,位置都在"新数据刚进入屏幕"的瞬间。这是典型的列表项创建开销:一进屏幕就现场构建组件、现场查数据,帧预算直接击穿。
定位清楚,优化的靶子就两个:让不在屏幕上的项别急着建,让重复创建的项尽量复用。
二、LazyForEach:按需创建的地基
列表数据量大时,ForEach 会把所有项一次性创建到位,几百条就是几百个组件的构建成本。换成 LazyForEach 配合 IDataSource:只创建可视区附近的项,滑到哪建到哪,数据变化通过监听器通知刷新。
改完第一版,超时帧明显变稀,但没消失。原因藏在细节里:
- 键值生成器要认真写:键值决定框架能不能正确识别"哪一项变了"。用默认的下标当键值,删除中间一项时后面全部错位重刷——键值必须是稳定唯一的业务 ID;
- cachedCount 给滑动留缓冲:只渲染可视区,快速滑动时新项来不及建。按屏高比例给可视区外预建几条,丝滑和内存之间取平衡,码上清单给的值实测刚好抹平超时帧。
三、组件复用:把构建成本摊薄
LazyForEach 解决"什么时候建",@Reusable 解决"建多少次":标记可复用的组件滑出屏幕后不销毁,滑回来时复用实例只刷新数据。待办卡片这种"长一个样"的列表项,是天生的复用素材。
改造要点是"数据驱动视图"要彻底:onDidChangeState 类的复用回调里,把卡片的全部可见状态(标题、勾选态、优先级色)都从新数据重算一遍。漏掉一个状态,就会出现"滑动几次之后某张卡片显示上一条待办的内容"——复用引入的典型脏数据,测试时要专门滑几轮做对照。
四、效果与边界
优化后重新采样:同样几百条数据,滑动全程无超时帧,内存占用没有因为预建缓冲明显上涨。回头看这轮优化,改动集中且可控:列表项键值、cachedCount、组件复用三处,加起来不到百行。
边界也记两笔:
- 不是所有列表都值得上这套:几十条的短列表用 ForEach 完全够,引入 LazyForEach 是白增加复杂度。优化要有数据支撑,没有超时帧就别动手;
- 列表项本身要轻:复用和按需加载救不了一个本身就重的列表项——嵌套过深、build 里做计算,这些是地基问题,得回到布局和数据层去解。
小结与阶段收束
至此,码上清单从环境搭建、踩坑复盘、状态管理,到调试、生命周期、卡片、包管理、一多、持久化、列表性能,主线上的十件事都过了一遍。HarmonyOS NEXT 的开发心智可以浓缩成三句:状态驱动 UI、工具链说话、数据按形状归位。这个系列的第一阶段就收在这里,后续有新的实战心得再续。
*本文环境:DevEco Studio 5.x / HarmonyOS NEXT(API 14+)。LazyForEach 与组件复用细节以官方《渲染控制》《性能优化指导》为准。系列上一篇:《【鸿蒙心迹】数据持久化实战》。*