语言层面的优化
使用明确的数据类型,避免使用模糊的数据类型,例如ESObject。
使用AOT模式
AOT就是提前编译,将字节码提前编译成机器码,这样可以充分优化,从而加快执行速度。
未启用AOT时,一边运行一边进行机器码的生成。
开启AOT后,设备能直接运行已经提前优化过的机器码,大大提高执行速度。
应用启动优化
应用阶段划分:
- 第一阶段:应用进程的创建和初始化
- 第二阶段:App和Ability的初始化
- 第三阶段:Ability生命周期
- 第四阶段:加载绘制首页
每个启动阶段的优化策略:
- 第一阶段优化:设置合适分辨率的应用图标
- 第二阶段优化:减少首页Ability或者Page中import的模块数量,不是首页必须的模块可以使用动态异步加载,如await import('Page')
- 第三阶段优化:Ability生命周期方法中,对于耗时操作进行异步处理
- 第四阶段优化:延迟加载,减少不必要的首页内容。例如使用LazyForEach替换ForEach
LazyForEach替换ForEach
LazyForEach是一种懒加载的模式,在循环绘制组件时能显著提升页面的加载速度。结合cacheCount方法能控制列表的缓存数量,实现更优的滑动体验。
减少丢帧卡顿
- 避免在主线程上执行耗时操作:将耗时操作放在TaskPool或者Worker等后台进程中执行,从而防止主线程负载过高。
- 减少渲染进程的冗余开销:使用资源图代替绘制、合理使用renderGroup、尺寸位置使用整数。
- 减少试图嵌套层级
- 组件复用
- 控制状态变量关联的组件数量
- 在对象上谨慎使用状态变量进行关联
优化案例
组件转场动画推荐使用transition,不推荐使用animateTo方法。
减少animateTo方法的使用数量,一起变更比分开变更更加高效。
多次animateTo时统一更新状态变量,减少多次更新状态变量导致的开销。
使用RenderGroup可以缓存组件及其子组件的绘制,从而降低绘制负载优化渲染性能。适合没状态绑定的不变组件,如果有状态绑定,当状态变化时缓存就是失效了。
使用@Reusable标记复用组件,适用频繁创建和销毁的组件,或反复切换条件渲染的控制分支且控制分支中的组件子树结构相同。
不推荐使用更新单个状态变量的形式控制多个组件的更新(命令式);
推荐使用状态变量和组件一对一绑定的方式,以数据变更驱动组件的刷新(声明式);
合理控制状态变量更新范围,避免关联刷新大量组件。关联变化较大的状态变量可以通过对象组合成一个状态变量,针对渲染成本较高的组件建议使用独立的状态变量进行关联。
理解@Prop和@ObjectLink的区别:@Prop是深拷贝关联,@ObjectLink是浅拷贝关联,因此优先推荐使用@ObjectLink的方式,从而减少系统内存开销。
性能调优工具
Profile调优工具
合理使用布局
组件布局属性(width、height、padding、margin等)大小发生变化会导致受影响的整个组件树重新更新,而非布局属性(Color、BackgroundColor、opacity等)的变化仅影响组件自身。这一点跟Web界面的渲染机制类似,因此我们在更新界面元素时,尽量减少布局属性的变化,防止影响整个组件的重新渲染。如果某些组件需要经常变化,可以将组件置于一个固定布局(这个布局内,布局属性固定)内,将影响固定在这个固定布局内部,从而减少对其他组件的影响。
精简节点数
- 移除冗余节点
- 使用扁平化布局减少节点数

扁平化方法:通过将嵌套结构摊开,减少中间节点,从而提升渲染速度。常用方法有:
- 通过RelativeContainer 相对布局实现扁平化
- 通过锚点定位实现扁平化
- 通过Grid布局实现扁平化
利用布局边界减少计算
对于能够在初期给定宽高的组件,在进行UI描述时尽量给定宽高数值,能够减少由于容器尺寸变化造成的重新测算过程的性能。
合理控制元素的显示与隐藏
首次绘制时,if会根据是否为true决定是否创建组件,而visibility组件无论是否显示都要创建组件。
再次显示时,if由于首次没有创建组件,再次显示时会创建组件,并经过Measure和Layout阶段。而visibility组件已经创建过,只需要经过Measure和Layout阶段。
- 只有初始的一次渲染或者交互次数很少的情况下,建议使用if条件判断来控制元素的显示与隐藏效果,对于内存有较大提升。
- 如果会频繁响应显示与隐藏的交互效果,建议使用切换Visibility.None和Visibility.Visible来控制元素显示与隐藏,提高性能。