欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Flutter 自定义动画在 OpenHarmony 手机上的性能优化实践

前言

最近在做 Flutter for OpenHarmony 项目时,项目里加了不少动画效果。

包括:

  • 首页 Banner 动画
  • 卡片缩放
  • 页面切换过渡
  • 按钮点击反馈
  • Loading 动画

刚开始在模拟器里看着还挺正常。

但真正放到 OpenHarmony 真机上之后,问题慢慢开始出现:

  • 动画掉帧
  • 页面发卡
  • 滑动时动画不流畅
  • GPU 占用偏高
  • 多动画同时执行时明显卡顿

尤其是在一些中低端设备上,问题会更明显。

后面花了一段时间做动画性能优化,整体流畅度改善了很多。

这篇文章主要记录一下这次 Flutter 动画优化过程,以及我在 OpenHarmony 设备上踩过的一些坑。


一、最开始的动画实现

项目初期很多动画其实写得比较“直接”。

比如按钮点击缩放:


AnimatedContainer(
  duration: const Duration(milliseconds: 300),
  transform: Matrix4.identity()..scale(scale),

  child: child,
)

或者:


AnimatedOpacity(
  duration: const Duration(milliseconds: 300),
  opacity: visible ? 1 : 0,
)

小页面问题不大。

但页面复杂后:

动画越来越多。

性能问题就开始明显了。


二、OpenHarmony 真机上的一个明显现象

这个是我最开始注意到的问题。


页面滑动 + 动画同时执行

例如:

商品列表滑动过程中:

顶部 Banner 同时自动轮播。

这时候会明显感觉:

  • 滑动不跟手
  • FPS 波动
  • 动画偶发卡顿

Android 上也会有一点。

但 OpenHarmony 设备上更容易观察到。

尤其 GPU 曲线会明显升高。


三、不要滥用 AnimatedContainer

这个是我后面总结出来很重要的一点。


为什么

AnimatedContainer 虽然很好用。

但它本质上会触发:

  • layout
  • paint
  • rebuild

如果页面里大量使用:

性能开销会比较明显。


后来的优化方案

简单透明度动画:

改成:


FadeTransition

位移动画:

改成:


SlideTransition

缩放动画:

使用:


ScaleTransition

相比 AnimatedContainer:

性能会稳定很多。


四、AnimationController 的正确使用

这里其实是 Flutter 动画里最核心的部分。


基础结构


class DemoPageState extends State<DemoPage>
    with SingleTickerProviderStateMixin {

  late AnimationController controller;

  @override
  void initState() {

    super.initState();

    controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
  }

  @override
  void dispose() {

    controller.dispose();

    super.dispose();
  }
}

一个我踩过的坑

刚开始有几个页面:

忘记 dispose。

结果:

页面退出后动画还在跑。

后面连续切页面:

CPU 占用越来越高。

在 OpenHarmony 真机上特别明显。

所以:


controller.dispose()

一定别忘。


五、减少动画区域重绘

这是这次优化里效果最明显的一部分。


问题

我之前很多动画直接包整个页面:


AnimatedBuilder(
  animation: controller,
  builder: (_, child) {

    return Scaffold(
      body: ...
    );
  },
)

结果:

动画执行时整个页面都在 repaint。


后来的优化

只让局部区域参与动画。


AnimatedBuilder(
  animation: controller,

  child: const GoodsCard(),

  builder: (_, child) {

    return Transform.scale(
      scale: animation.value,
      child: child,
    );
  },
)

这样:

child 不会重复 build。

性能会明显好很多。


六、RepaintBoundary 的实际效果

这个优化在鸿蒙设备上真的挺明显。


使用场景

例如:

  • Banner
  • 商品卡片
  • 视频区域
  • Loading 动画

这些复杂区域。


优化方式


RepaintBoundary(
  child: BannerWidget(),
)

作用:

隔离重绘区域。

避免动画导致整个页面 repaint。


实际测试

优化前:

页面动画时:

GPU 曲线波动很明显。

优化后:

掉帧明显减少。


七、不要同时跑太多动画

这个问题我在首页踩得特别明显。


当时的首页

同时存在:

  • Banner 自动轮播
  • 卡片渐变
  • 数字滚动
  • 按钮缩放
  • Loading 动画

模拟器没太大感觉。

真机上直接开始掉帧。


后来的处理

我做了几个优化:

1. 非必要动画直接删

有些动画纯装饰。

实际意义不大。

删掉后体验反而更稳定。


2. 控制动画时长

之前:


Duration(milliseconds: 1000)

太长。

后面统一:


200~300ms

会更自然。


3. 页面不可见时暂停动画

例如:


controller.stop()

页面返回时:


controller.forward()

这样能减少后台资源消耗。


八、列表动画是重灾区

这个我建议一定重点优化。


错误做法

列表每个 Item:

都加复杂动画。


ListView.builder(
  itemBuilder: (_, index) {

    return AnimatedContainer(
      duration: Duration(milliseconds: 500),
    );
  },
)

数据量一大:

直接开始卡。


后来的方案

只对:

  • 首屏
  • 当前点击项
  • 少量核心元素

做动画。

列表滚动性能会稳定很多。


九、OpenHarmony 下的一个特殊现象

这里是我这次适配里发现的一个细节。


问题现象

页面频繁 push/pop 后:

部分动画会偶发:

  • 停止
  • 卡死
  • 不执行

Android 上复现概率低。

鸿蒙设备更容易出现。


后来的解决方式

我后来统一在:


didChangeDependencies()

里检查动画状态。

并且:

页面销毁时一定 dispose。

目前已经比较稳定。


十、如何观察动画性能

这个我建议一定开。


开启性能面板


MaterialApp(
  showPerformanceOverlay: true,
)

重点观察:

  • GPU 曲线
  • UI 曲线

我的一些经验

GPU 高

通常是:

  • repaint 太多
  • 图片太大
  • 动画区域太大

UI 高

通常是:

  • build 太频繁
  • 页面计算太重
  • Widget 结构复杂

这个在 OpenHarmony 真机上挺有参考价值。


十一、优化前后效果

优化前:

问题 表现
动画掉帧 明显
页面卡顿 存在
GPU 占用 偏高
列表动画 不流畅

优化后:

项目 效果
动画流畅度 提升明显
页面响应 更顺滑
GPU 曲线 更稳定
多动画场景 基本正常

目前这套方案已经在项目里稳定运行了一段时间。


十二、总结

这次做 Flutter 动画优化,一个比较深的感受是:

Flutter 动画本身能力其实很强。

但如果:

  • 动画区域太大
  • rebuild 太频繁
  • 多动画叠加
  • 列表里乱加动画

性能问题会非常明显。

尤其在 OpenHarmony 真机环境里:

GPU 压力会比想象中更敏感。

我现在项目里的原则基本是:

  • 能不用复杂动画就不用
  • 动画只做局部
  • 尽量减少 repaint
  • 页面不可见时暂停动画

整体稳定性会好很多。

后面我还准备继续研究:

  • Impeller 渲染器
  • Flutter Shader 动画
  • OpenHarmony GPU 渲染优化
  • Flutter 游戏动画性能

希望这篇文章能给正在做 Flutter for OpenHarmony 开发的同学一点参考。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐