ArkUI进阶-性能优化

ArkUI进阶-性能优化

布局性能优化

基本布局流程

在ArkUI的布局过程中,应用侧会根据前端UI描述创建后端的页面节点树,包含处理UI组件属性更新,布局测算,事件处理等逻辑。

例如上述布局:

  1. 应用会根据我们的代码,创建对应的node节点树,其中,Custom Node表示自定义组件节点,Frame Node节点表示系统组件节点。
  2. 在这个过程中,UI线程会对每个元素进行测算measure和布局lauout,来确定具体的位置和大小,measure阶段负责确定组件的测量宽高,也就是该组件元素占用的屏幕大小,layout阶段会确定最终宽高和四个顶点的位置。
  3. 根据页面节点树,生成当前界面描述数据结构--渲染树。渲染树由RenderNode渲染节点组成,描述了具体元素在屏幕上的布局信息,包含大小、位置以及一些其他属性。
  4. 渲染服务的渲染线程会根据渲染树的信息执行相应的绘制工作。

在布局阶段中,如果视图嵌套层级较深,或者页面节点过多,会导致在Measure和layout过程中,通过遍历测量组件大小和边界的时间过长。所以布局性能优化,可以从减少节点数或者优化布局测算时间方面来考虑。

精简节点数

首先我们先看一下相同数量节点嵌套和平铺的情况下,对性能的影响,通过使用IDE的profiler工具进行抓取,可以得知:

从上边我们可以看出,在相同组件、相同数量的情况下,嵌套和平铺对性能的影响差距不是很大,主要影响性能的还是节点数量,所以我们在进行布局的时候,应该尽量减少参与布局的节点数,来减少布局的性能消耗。

主要有两个优化方向:

  1. 移除冗余节点。
  2. 使用扁平化布局,减少层级嵌套,如RelativeContainerGrid等。

合理控制元素的隐藏与显示

在ArkUI中,控制元素隐藏和显示,一般有两种方式,使用条件语句控制,或者使用visibility属性来控制。

我们来对比使用条件渲染语句和使用visibility属性来控制时,measure和layout耗时区别:

首次渲染:

我们可以看到,使用条件渲染语句时,当条件为false时,对应组件不参与measure和layout阶段。使用visibility属性进行控制的时候,无论组件是否显示,都会参与measure阶段,如果visibility为none,那么组件不参与layout阶段。

切换显示

我们可以看到,切换显示状态的时候,使用条件渲染语句,会根据条件来判断组件是否创建,切换过程会出现较大的性能消耗,且每次切换消耗相同。使用visibility的时候,性能消耗要小很多。

综上所述,在控制组件的显示与隐藏时,我们可以遵循以下原则:

  • 对性能要求较高,且会频繁切换显示与隐藏的情况下,使用visibility属性进行控制。
  • 组件创建性能消耗较大,且初始状态下不可见,并且不会频繁切换的情况下,使用条件渲染语句进行控制。

给定组件的宽高

在ArkUI中,我们给组件设置宽高的方式,一般分为三种:设置固定值、百分比宽高、不设置宽高。

我们对比三种情况下的measure和layout的耗时

初次加载时,三种情况消耗差距不大,原因是初次加载的时候,所有的组件都参与了measure和layout过程。

在重绘的过程中,我们可以看到,给定宽高的组件,所消耗的性能明显小于其他两种方式,原因是修改宽高触发重绘的情况下, 给定内部组件宽高时,内部组件可以重用初次measure和layout数据,不设置宽高和百分比宽高的,由于父容器宽高发生了变化,所以需要参与measure和layout过程。

使用推荐的布局组件

越是复杂的布局,measure和layout的过程越是耗时,比如grid组件就会比row组件耗时,但是如果使用grid组件,可以明显减少页面的节点数量或者是嵌套层级数量,那么此时所节省的性能会明显优于grid组件多消耗的性能。

长列表加载性能优化

长列表优化概述

针对长列表加载场景,对列表渲染速度、页面滑动帧率、内存占用大小等方面进行优化,主要有以下几个方面

  • 懒加载:提供列表数据按需加载的能力,解决一次性加载列表项耗时过长,占用过多资源的问题,提升页面加载速度。
  • 缓存列表项:提供屏幕可视区域外列表缓存长度的自定义调节能力,配合懒加载使用,缓存页面数据,预加载页面外列表项,提升列表滑动体验。
  • 组件复用:提供可复用组件对象的缓存资源池,通过重复使用已经创建并缓存的组件对象,降低相同组件短时间内频繁创建和销毁的消耗,提升渲染效率。
  • 布局优化:使用扁平布局,减少视图嵌套层级和节点数,提升渲染效率。

懒加载

当列表数据量较小且布局较为简单的时候,我们可以使用ForEach渲染语句。

当列表数据量较大时,使用lazyForEach渲染语句实现懒加载的效果。

使用lazyForEach渲染语句时,最小可以做到仅加载渲染屏幕当前显示的列表项。

缓存列表项

我们使用了lazyForEach懒加载时,默认只会渲染当前屏幕显示的列表项,那么当我们快速滑动的时候,就会出现白块的现象。

lazyForEach可以通过设置cachedCount来缓存或预加载一定数量的列表项,比如当前屏幕最大可以显示5条,cachedCount为3,那么此时挂载在组件树上的列表项,最多可以是11条。

组件复用

  1. 在item列表项的自定义组件头部添加@Reusable装饰器,标识该组件拥有复用的能力。
  2. 实现可复用自定义组件的生命周期aboutToReuse方法,也就是我们的数据填充逻辑。
  3. 在ListItem组件上设置可复用组件的ReuseId
相关推荐
johnsong8 小时前
深度拆解:150M循环模型如何用循环推理击败大Transformer
android·深度学习·transformer
CedarQR9 小时前
云卓 G20 遥控器 Android 开发实录:从 USB 设备到读取摇杆/按键通道值
android·linux·无人机
pengyu10 小时前
【Kotlin 协程修仙录 · 炼虚境 · 初阶】 | 虚空造物:Channel 基础与协程间通信的管道艺术
android·前端·kotlin
小强闯江湖10 小时前
ViewCompose:让原生 Android View 进入声明式时代
android·开源·kotlin
2501_9197490311 小时前
华为鸿蒙免费戒咖啡APP—小羊戒咖
华为·harmonyos·鸿蒙
摇滚侠12 小时前
《SpringBoot 3:入门与应用实战》第 6 章 Spring Boot 最佳实践 阅读笔记 12
android·spring boot·笔记
小小龙学IT13 小时前
C++ 性能优化:CPU 缓存与数据布局优化深度解析
c++·缓存·性能优化
mmsx13 小时前
Android 宠物健康服务平台实战:从架构设计到主题换肤完整解析(源码和文档)
android·架构·sqlite·app·源码·宠物
、如果13 小时前
ima Skills 自进化实战:三层结构、反馈与版本验证
android·人工智能·ai编程
2501_9197490313 小时前
华为鸿蒙免费戒烟APP—小羊戒烟
华为·harmonyos·鸿蒙