HarmonyOS 鸿蒙Next中滚动卡顿

HarmonyOS 鸿蒙Next中滚动卡顿 Lottie动画在列表中滚动卡顿如何优化

3 回复

【背景知识】

  • lottie是一个适用于OpenHarmony的动画库,它可以解析Adobe After Effects软件通过Bodymovin插件导出的JSON格式的动画,并在移动设备上进行本地渲染;
  • 卡顿是一种在视觉上表现为画面不流畅、停顿或延迟的现象,它可能由多种因素引起,丢帧是其中一个重要原因;当设备性能不足时,可能无法及时处理和渲染所有的帧,从而导致丢帧,进而引发卡顿。

【解决方案】

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: 'xxx',
        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.info('onVisibleAreaChange:' + 'play' + ' index: ' + this.index)
      this.animationItem?.play()
    } else {
      console.info('onVisibleAreaChange:' + 'stop' + ' index: ' + this.index)
      this.animationItem?.stop()
    }
  })

更多关于HarmonyOS 鸿蒙Next中滚动卡顿的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS Next滚动卡顿可能由以下原因导致:

  1. UI渲染性能不足,列表组件未启用复用机制;
  2. 主线程执行了复杂计算或同步操作,阻塞了UI更新;
  3. 内存占用过高导致系统频繁触发垃圾回收;
  4. 图像绘制层级过深或存在冗余重绘;
  5. 系统资源调度策略影响渲染优先级。

可通过DevEco Studio的性能分析器检查渲染帧率和线程状态,使用ArkTS的LazyForEach优化列表渲染,确保异步处理数据加载任务。

在HarmonyOS Next中,Lottie动画在列表滚动时出现卡顿,通常可通过以下方式优化:

  1. 降低动画复杂度:检查Lottie JSON文件,减少图层数量、路径节点或渐变效果,优先使用静态资源替代高帧率动画。
  2. 启用硬件加速:确保动画层使用setLayerType(LAYER_TYPE_HARDWARE),利用GPU渲染减轻主线程负担。
  3. 列表项复用优化:在ListContainerRecycleContainer中,对Lottie视图进行缓存管理,避免滚动时重复解析JSON。
  4. 动态控制播放:监听滚动事件,在滚动时暂停动画(调用pauseAnimation()),停止后恢复播放,减少渲染竞争。
  5. 预加载与帧限制:提前初始化Lottie实例,限制动画帧率(如30fps),并通过setMaxFrame()截取必要片段。
  6. 内存监控:使用DevEco Studio性能分析工具检查内存泄漏,确保及时释放未使用的Lottie对象。

示例代码片段:

// 滚动时暂停动画
listContainer.setOnScrollListener(new OnScrollListener() {
    @Override
    public void onScroll(int firstVisibleItem) {
        lottieAnimator.pauseAnimation();
    }
    
    @Override
    public void onScrollStop() {
        lottieAnimator.resumeAnimation();
    }
});

通过综合运用上述策略,可显著提升滚动流畅度。

回到顶部