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
相关推荐
键盘鼓手苏苏12 小时前
Flutter 三方库 p2plib 的鸿蒙化适配指南 - 实现高性能的端到端(P2P)加密通讯、支持分布式节点发现与去中心化数据流传输实战
flutter·harmonyos·鸿蒙·openharmony
加农炮手Jinx12 小时前
Flutter for OpenHarmony:postgrest 直接访问 PostgreSQL 数据库的 RESTful 客户端(Supabase 核心驱动) 深度解析与鸿蒙适配指南
数据库·flutter·华为·postgresql·restful·harmonyos·鸿蒙
加农炮手Jinx12 小时前
Flutter 组件 heart 适配鸿蒙 HarmonyOS 实战:分布式心跳监控,构建全场景保活检测与链路哨兵架构
flutter·harmonyos·鸿蒙·openharmony
钛态12 小时前
Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos)
android·网络协议·flutter·http·华为·中间件·harmonyos
王码码203512 小时前
Flutter for OpenHarmony:Flutter 三方库 algoliasearch 毫秒级云端搜索体验(云原生搜索引擎)
android·前端·git·flutter·搜索引擎·云原生·harmonyos
王码码203512 小时前
Flutter 三方库 dns_client 的鸿蒙化适配指南 - 告别 DNS 劫持、探索 DNS-over-HTTPS (DoH) 技术、构建安全的鸿蒙网络请求环境
flutter·harmonyos·鸿蒙·openharmony·dns_client
键盘鼓手苏苏12 小时前
Flutter 组件 highlighter 适配鸿蒙 HarmonyOS 实战:高性能语法高亮,构建大规模代码分析与文本染色架构
flutter·harmonyos·鸿蒙·openharmony
国医中兴12 小时前
Flutter 三方库 langchain_google 的鸿蒙化适配指南 - 链接 Gemini 智慧中枢、LangChain AI 实战、鸿蒙级智能应用专家
flutter·langchain·harmonyos
左手厨刀右手茼蒿12 小时前
Flutter for OpenHarmony: Flutter 三方库 shamsi_date 助力鸿蒙应用精准适配波斯历法(中东出海必备)
android·flutter·ui·华为·自动化·harmonyos
雷帝木木12 小时前
Flutter 三方库 http_client_interceptor 的鸿蒙化适配指南 - 实现原生 HttpClient 的全量请求拦截、支持端侧动态 Headers 注入与网络流量审计实战
flutter·harmonyos·鸿蒙·openharmony·http_client_interceptor