鸿蒙原生APP性能优化之UI组件优化

往期推文全新看点

应用启动到UI页面展示过程包含框架初始化、页面加载和布局渲染三个步骤。其中页面加载和布局渲染的主要流程如下:

图1页面首次加载过程流程图

  • 在执行页面文件时,前端UI描述会在后端创建相应的FrameNode节点树。该树主要用于处理UI组件属性更新、布局测算、事件处理。每个树节点和前端UI组件是一一对应的关系。
  • FrameNode节点树生成之后,根节点开始创建布局任务。该任务遍历所有子节点并创建子节点的布局包装任务。布局包装任务包括执行相关测算和布局任务。
  • 布局包装任务完成后,每个FrameNode将创建相应的渲染包装任务并进行内容绘制。

可以看到,应用启动后页面加载和渲染的性能与FrameNode树上的节点数量以及每个节点上的属性相关。因此,为缩短页面加载和布局渲染时长,在前端使用UI组件时可以考虑以下优化方案:

  • 避免在自定义组件的生命周期内执行高耗时操作:自定义组件创建后在渲染前会调用其生命周期回调函数,若函数中包含高耗时操作将阻塞UI渲染,将增加主线程负担。
  • 按需注册组件属性:后端在创建FrameNode节点树时,对于组件上注册的每个属性也会保存在FrameNode节点上,包括渲染类属性集合(如颜色)和布局类属性集合(如长宽,对齐方式)。在FrameNode执行布局包装任务和渲染包装任务时,属性集合将作为输入参与。因此,在应用开发中应按需注册组件属性,避免设置冗余属性。
  • 使用@builder函数代替自定义组件:前端定义的每一个自定义组件都会在后端FrameNode节点树上创建一对一的CustomNode类型的节点。CustomNode类作为FrameNode的子类,用于处理自定义组件相关业务逻辑。当在页面上大量使用自定义组件时,会成倍增加FrameNode节点树上CustomNode类型的节点数量,增加页面创建和渲染时长。因此,在满足业务需求的前提下,可以优先使用@builder函数代替自定义组件。
  • 合理使用布局容器组件:ArkUI提供了一系列布局容器组件 用于开发者快速搭建页面。不同的业务场景应选择合适的布局容器组件,并合理使用该组件的特性功能可以有效缩短页面布局时长。

避免在自定义组件的生命周期内执行高耗时操作

图2自定义组件生命周期流程图

如上图所示,自定义组件创建完成之后,在build函数执行之前,将先执行aboutToAppear()生命周期回调函数。此时若在该函数中执行耗时操作,将阻塞UI渲染,增加UI主线程负担。因此,应尽量避免在自定义组件的生命周期内执行高耗时操作。对于复杂计算的耗时场景,可以将计算结果进行缓存处理。对于不需要等待结果的高耗时任务,可以采用多线程处理该任务,通过并发的方式避免主线程阻塞。在aboutToAppear()生命周期函数内建议只做当前组件的初始化逻辑,其他业务逻辑可以按需提前或延后处理。假设在首页视频列表中的子组件内需要初始化创建一个复杂播放器对象,该对象的创建非常耗时。若在该组件的aboutToAppear()函数中对创建该对象,当首页加载渲染时,列表内每个子组件的渲染都将等待相应的播放器对象初始化创建完成,此时页面加载将非常耗时甚至可能出现白屏。伪代码如下:

@Component
export struct VideoCard{
  // ...
  aboutToAppear(): void {
    // 创建复杂对象任务,若该任务执行耗时1s,则组件将在1s后再渲染
    this.createComplexVideoPlayer();
  }
  // ...
}

@Component
export struct CardList {
  @State videoList: VideoItem[] = getVideoList();

  build() {
    List() {
      ForEach(this.videoList, (item: VideoItem) => 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值