• 作者:老汪软件技巧
  • 发表时间:2024-10-07 10:02
  • 浏览量:

避免在生命周期函数执行耗时操作

在build函数执行之前,将先执行aboutToAppear()生命周期回调函数。若在该函数中执行耗时操作,将阻塞UI渲染,增加UI主线程负担。可以将耗时操作放到子线程或者使用不耗时的函数。例如在aboutToAppear中应该避免使用ResourceManager的getXXXSync接口入参中直接使用资源信息,推荐使用资源id作为入参,推荐用法为:resourceManager.getStringSync($r('app.string.test').id)。第一种方式获取的是拷贝对象,发生了一次深拷贝,第二种方式直接获取原对象的引用。

使用@Builder方法代替自定义组件

ArkUI中使用自定义组件时,在build阶段将在后端FrameNode树创建一个相应的CustomNode节点,在渲染阶段时也会创建对应的RenderNode节点,如下图所示。

减少自定义组件的使用,尤其是自定义组件在循环中的使用,将成倍减少FrameNode节点树上CustomNode节点数量,有效缩短页面的加载和渲染时长。@Builder函数不会在后端FrameNode节点树上创建一个新的树节点。如果组件仅仅是用来纯展示,不需要更新,优先使用@Builder函数代替自定义组件。

按需注册组件属性

组件每个属性保存在FrameNode节点上,组件设置了大量属性且该组件被大量使用,对应用的整体性能会产生较大影响。应按需注册组件属性,避免设置冗余属性。如果必须设置很多属性,可以考虑AttributeModifier动态注册组件属性的方式。动态注册组件属性可以实现差异更新属性,当组件创建或者更新时,重新执行组件的样式属性对象的更新接口。通过key找到对应的属性修改器对象进行差异对比,若有更新变化再通知native侧进行属性更新。

// 1.自定义属性修改器,该类实现了AttributeModifier接口
class RowModifier implements AttributeModifier {
  private customImage: ResourceStr = '';
  private static instance: RowModifier;
  constructor() {}
  setCustomImage(customImage: ResourceStr) {
    this.customImage = customImage;
    return this;
  }
  // 采用单例模式,避免为每个组件都创建一个新的修改器,增加创建产生的性能开销
  public static getInstance(): RowModifier {
    if (!RowModifier.instance) {
      RowModifier.instance = new RowModifier();
    }
    return RowModifier.instance;
  }
  // 2.实现AttributeModifier接口的applyNormalAttribute方法,自定义属性设置的逻辑
  applyNormalAttribute(instance: RowAttribute) {
    if (this.customImage) {
      instance.backgroundImage(this.customImage);
      instance.backgroundImageSize(ImageSize.Cover);
     } else {
      instance.backgroundColor(DEFAULT_BACKGROUND_COLOR);
      instance.justifyContent(FlexAlign.Center);
      // instance.padding(2)
      // instance.margin(2)
      // instance.opacity(1)
      // instance.clip(false)
      // instance.layoutWeight(1)
      // instance.backgroundBlurStyle(BlurStyle.NONE)
      // instance.alignItems(VerticalAlign.Center)
      // instance.borderWidth(1)
      // instance.borderColor(Color.Pink)
      // instance.borderStyle(BorderStyle.Solid)
      // instance.expandSafeArea([SafeAreaType.SYSTEM])
      // instance.rotate({ angle: 5 })
      // instance.responseRegion({x: 0})
      //instance.mouseResponseRegion({x: 0})
      // instance.constraintSize({minWidth: 25})
      // instance.hitTestBehavior(HitTestMode.Default)
      //instance.backgroundImagePosition(Alignment.Center)
      //instance.foregroundBlurStyle(BlurStyle.NONE)
    }
    instance.size({ width: 50, height: 50 });
    instance.borderRadius(25);
  }
}
@Component
struct Avatar {
  @ObjectLink user: User;
  build() {
    Row() {
      if (!this.user.avatarImage) {
        Text(this.user.name.charAt(0))
          .fontSize(28)
          .fontColor(Color.White)
          .fontWeight(FontWeight.Bold)
      }
    }
    // 3.将自定义RowModifier类作为参数传入,实现按需注册属性
    .attributeModifier(RowModifier.getInstance().setCustomImage(this.user.avatarImage))
  }
}

精简节点数

移除冗余的节点,可能会在Row容器包含一个Row容器。如下代码,Row容器Row容器,这种嵌套实际是多余的,并且会给布局层次结构造成不必要的开销。

执行转破产耗时多久__耗时操作是什么

Row() {
  Row(){
    Image()
    Text()
  }
  Image()
}

修改后的代码

Row() {
  Image()
  Text()
  Image()
}

合理使用布局容器组件利用布局边界减少布局计算

如果组件的宽高不需要自适应,那就写死宽高。当其组件外部的容器尺寸发生变化时,组件本身的宽高固定,就不需要重新测量。

合理控制元素显示与隐藏

使用Visibility.None、if条件判断等都能够元素显示与隐藏。如果频繁修改元素的显示与隐藏,通过visibility属性控制,可以省去组件创建的时间,直接进入渲染过程。交互次数很少的情况下,使用if条件判断来控制元素的显示与隐藏效果,对于内存有较大提升。

Scroll嵌套List场景下,给定List组件宽高

Scroll嵌套List时:

优先使用组件属性代替嵌套组件

在实现文本浮层、按压遮罩或颜色叠加等场景时,通常会采用Stack布局嵌套组件的方式。实际上有些场景直接使用组件属性或借助系统API的能力就能实现,例如使用overlay属性可以实现浮层场景,使用ColorMetrics可以实现颜色叠加效果。直接使用组件属性可以减少Stack布局嵌套组件,减少组件节点数。