HarmonyOS 鸿蒙Next中Lottie动画在列表中滚动卡顿如何优化
HarmonyOS 鸿蒙Next中Lottie动画在列表中滚动卡顿如何优化
【问题现象】
列表中有Lottie动画,当Lottie动画播放时列表滚动卡顿,当Lottie动画播放结束之后,列表滚动恢复正常。如下图:
问题代码如下:
// 使用三方库[@abner](/user/abner)/refresh中的组件ListView构造列表
ListView({
items: this.array, // 数据源 数组,可以任意类型,自定义对象[],number[],string[]……
itemLayout: this.itemLayout, // 转成你需要的对象
listAttribute: (attr) => {
attr.edgeEffect = EdgeEffect.Spring // 设置阻尼效果
}
})
/**
* Describe:条目布局
* @param item 数据对象
* @param index 数据索引
*/
@Builder
itemLayout(): void {
Row() {
AnimatorLottieBase({
imagePath: "lottie/round_frame95/images/",
path: "lottie/round_frame95/data.json",
animateName: 'https://ali-dev-system.lrscloud3.com/avatarframe/round_frame95.zip',
autoplay: true,
loop: true, // 当loop为true时,滚动异常卡顿
})
.height(50)
.width(50)
Blank(100)
}
}
【背景知识】
- Lottie是一个适用于OpenHarmony的动画库,它可以解析Adobe After Effects软件通过Bodymovin插件导出的JSON格式的动画,并在移动设备上进行本地渲染;
- 卡顿是一种在视觉上表现为画面不流畅、停顿或延迟的现象,它可能由多种因素引起,丢帧是其中一个重要原因;当设备性能不足时,可能无法及时处理和渲染所有的帧,从而导致丢帧,进而引发卡顿。
【定位思路】
1. 用户同一时间加载过多动画,导致性能过载
观察到界面中的Lottie动画数量很多,通过日志打印发现进入动画界面时会初始化多个动画,这样的定义方式会将统一渲染服务进程占满,导致进程在刚进入该界面时不仅要处理动画的初始化,还要处理List列表的滑动,这时设备性能不足,从而丢帧引发卡顿。
2. 多余的动画渲染没有及时销毁,造成不必要的性能损耗
该界面同时加载了多个动画,显示在界面中的15个动画在播放,其余30+个在界面之外的动画也同时在播放。
【解决方案】
1. 合理使用动画生命周期,在首次进入界面时,不过多初始化构造多余动画
上文发现使用ListView会在首次进入界面时构造全部数量(50)的动画,造成性能过载。使用List组件替代三方库@abner/refresh中的组件ListView后,通过日志可以看到首次进入只构造了在界面中显示的14个,随着慢慢向下滑动屏幕,使下方的动画进入界面内,List组件才会构造该动画,卡顿现象得到缓解。
代码示例如下:
List({ space: 10, initialIndex: 0 }) { // list上下树逻辑,ondisappear在出界面不会走;api13有需求做;
ForEach(this.array, (item: number) => {
ListItem() {
AnimatorLottieBase({
imagePath: "lottie/round_frame95/images/",
path: "lottie/round_frame95/data.json",
animateName: 'https://ali-dev-system.lrscloud3.com/avatarframe/round_frame95.zip',
autoplay: false,
loop: true, // 当loop为true时,滚动异常卡顿
index: item,
})
.height(50)
.width(50)
}
}, (item: string) => item)
}.width('90%')
.scrollBar(BarState.Off)
2. 动画滑出界面时,控制动画暂停,降低性能损耗
给画布组件添加onVisibleAreaChange属性,当该组件不可见时暂停该动画,可见时播放该动画。
代码示例如下:
.onVisibleAreaChange([0.0, 1.0],
(isVisible: boolean, currentRatio: number) => {
if (isVisible) {
console.log('onVisibleAreaChange:' + 'play' + ' index: ' + this.index)
this.animationItem?.play();
} else {
console.log('onVisibleAreaChange:' + 'stop' + ' index: ' + this.index)
this.animationItem?.stop();
}
})
【总结】
- 通过上文两步的调整,卡顿现象在基本场景下已经得到解决;该界面可共同展示多个循环播放的lottie动画,可满足大部分应用场景。
- 处理丢帧问题一般需要以下四个步骤:
1. 识别卡顿
首先使用AppAnalyzer检测应用是否存在性能问题,如果检测存在丢帧问题,然后使用Frame Profiler、SmartPerf Host等工具录制Trace,查看应用平均帧率、丢帧率等,同时查看丢帧发生的位置。
2. 分析丢帧原因
可以通过分析Trace,查看卡顿帧的详细信息。最后查看函数调用栈,查看是否存在耗时函数。
3. 选择优化方案
根据步骤分析的丢帧原因,选择适合的优化方案。
4. 验证优化效果
优化完成后需要重新测试验证丢帧问题是否得到解决,这里可以再次通过以上步骤来确认优化效果。
更多关于HarmonyOS 鸿蒙Next中Lottie动画在列表中滚动卡顿如何优化的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next中Lottie动画在列表中滚动卡顿如何优化的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
- 使用
List
组件替代ListView
,减少首次进入界面时动画的初始化数量,仅构造当前可见的动画。 - 为动画组件添加
onVisibleAreaChange
属性,当动画滑出界面时暂停播放,滑入界面时继续播放,降低性能损耗。