HarmonyOS应用性能优化实操宝典(如何快速提升应用性能)

性能优化实操宝典

概述

本文总结了实际开发应用时常见的性能优化规范,配合举例实际开发中常见的正反例代码,帮助开发者解决大部分性能问题。

性能规范总览目录

分类 规范(检查项) 实操方法 高频程度(5满分) 代码示例
响应时延/完成时延 不建议在aboutToAppear(),aboutToDisappear()等生命周期中执行耗时操作 排查所有的aboutToAppear和aboutToDisappear函数(或者通过Trace查看),查看是否有耗时操作,改为setTimeOut或者在TaskPool中执行。 5 代码示例
响应时延/完成时延 不要在回调函数中执行耗时操作(ArkUI接口回调、网络访问回调、await等) 排查所有的回调函数(或者通过Trace查看),尤其是ArkUI接口,网络回调函数,查看是否有耗时操作,是否使用了await操作,改为setTimeOut或者在TaskPool中执行。 5 代码示例
响应时延/完成时延/帧率 列表场景未使用LazyForEach+组件复用+缓存列表项 排查使用LazyForEach的代码,确认是否有使用组件复用(@Reusable)+缓存列表项(cachedCount)。 5 代码示例
完成时延 Web未使用预连接,未提前初始化引擎 在应用创建Ability的时候,在OnCreate阶段预先初始化内核,建议把引擎的初始化放在setTimeOut中。 5 代码示例
响应时延/完成时延 高频接口中不要打印Trace和日志 排查接口onTouch、onItemDragMove、onDragMove、onScroll、onMouse、onVisibleAreaChange、OnAreaChange、 onActionUpdate、animator的onframe、组件复用场景下的aboutToReuse,不建议在里面打印trace和日志。 5 代码示例
完成时延/帧率 组件复用里面有if语句,但是未使用reuseId 排查使用了@Reusable的自定义组件,查看build中给是否使用了if/else或ForEach等条件渲染语句,如果使用了,需要配合reuseId一起使用。 4 代码示例
响应时延/完成时延 不建议使用@Prop装饰器 全局搜索@Prop并且替换 4 代码示例
响应时延/完成时延 避免在ResourceManager的getXXXSync接口入参中直接使用资源信息 排查ResourceManager.getXXXSync接口,查看入参时需要使用getStringSync($r('app.media.icon').id)的形式, 如果未使用需要整改。 3 代码示例
响应时延/完成时延 展示用的自定义组件(数据从父组件中获取,无独立数据处理)使用@Builder替换 审视@Component标记的自定义组件,如果里面没有独立的生命周期处理逻辑,数据由父组件传递,建议@Builder替代。 3 代码示例
响应时延/完成时延/帧率 删除无具体逻辑的生命周期,ArkUI的函数回调等,删除冗余堵塞日志打印 排查所有的aboutToAppear、aboutToDisappear等生命周期函数,排查ArkUI的回调函数,如果函数中无具体业务逻辑, 例如只打印了日志,删除函数回调。 3 代码示例
响应时延/完成时延 删除未关联组件的状态变量装饰器 排查全局的状态变量装饰器,如果变量未关联组件,删除装饰器。 3 代码示例
帧率 crypto-js性能差 排查buffer.from关键字,加密建议使用原生的cryptoFramework,然后将buffer替换为base64helper,性能提升10倍以上, 且数据量越大越明显。 2 代码示例
响应时延/完成时延 不建议使用Marquee组件 排查Marquee关键字,使用Text的跑马灯模式(TextOverflow.MARQUEE)替代。 1 代码示例
完成时延 不能使用函数作为ArkUI组件的属性和组件复用的自定义组件的入参 查看属性是否有xx()函数写法,确认函数/方法中是否有耗时操作,替换成变量。 1 代码示例
完成时延 删除多余的import,会影响页面的启动时间 排查所有import代码,删除无用的引入。 1 代码示例
完成时延 不建议使用.linearGradient颜色渐变属性 排查linearGradient关键字,可以使用图片代替。 1 代码示例
完成时延/帧率 不要在for/while循环中执行耗时操作 排查for/while循环,查看里面是否有打印日志或者Trace。 1 代码示例
完成时延 变量初值不建议设置为undefined,需进行默认初始化 例如number设置为0,string设置为空字符串等,这样在使用过程中更不需要增加额外判空。 排查类中的变量,看看是否有初始化为undefined。 1 代码示例

性能优化规范

不建议在aboutToAppear()、aboutToDisappear()等生命周期中执行耗时操作

类型

响应时延/完成时延

解决方法

排查所有的aboutToAppear和aboutToDisappear函数(或者通过Trace查看),查看是否有耗时操作,改为setTimeOut或者在TaskPool中执行。

反例
@Entry
@Component
struct Index {
   
   
  @State private text: string = "";
  private count: numeber = 0;
  // 反例:在aboutToAppear接口中执行耗时操作,阻塞页面绘制。
  aboutToAppear() {
   
   
    // 耗时操作
    this.computeTask();
    let context = context.resourceManager.getStringSync($r('app.string.startup_text'));
  }

  computeTask(): void {
   
   
    this.count = 0;
    while (this.count < LARGE_NUMBER) {
   
   
      this.count++;
    }
    let context = getContext(this) as Context;
    this.text = context.resourceManager.getStringSync($r('app.string.task_text'));
  }
}
正例
@Entry
@Component
struct Index {
   
   
  @State private text: string = "";
  private count: numeber = 0;
  private readonly DELAYED_TIME: number = 2000; // 定时器设置延时2s

  // 正例:在aboutToAppear接口中对耗时间的计算任务进行了异步处理。
  aboutToAppear() {
   
   
    // 耗时操作
    this.computeTaskAsync(); // 异步任务
    let context = getContext(this) as Context;
    this.text = context.resourceManager.getStringSync($r('app.string.startup_text'));
  }

  computeTask(): void {
   
   
    this.count = 0;
    while (this.count < LARGE_NUMBER) {
   
   
      this.count++;
    }
    let context = getContext(this) as Context;
    this.text = context.resourceManager.getStringSync($r('app.string.task_text'));
  }

  // 运算任务异步处理
  private computeTaskAsync(): void {
   
   
    setTimeout(() => {
   
   
      // 这里使用setTimeout来实现异步延迟运行
      this.computeTask();
    }, DELAYED_TIME)
  }
}
高频程度&收益(5满分)

5

不要在回调函数中执行耗时操作(ArkUI接口回调、网络访问回调、await等)

类型

响应时延/完成时延

解决方法

排查所有的回调函数(或者通过Trace查看),尤其是ArkUI接口,网络回调函数,查看是否有耗时操作,是否使用了await操作,改为setTimeOut或者在TaskPool中执行。

反例
import http from '@ohos.net.http';
        
aboutToAppear() {
   
   
  // ...
  const b = await this.requestB();
}

async requestB(): {
   
    // 创建任务项
  return http.createHttp();
}
正例
aboutToAppear() {
   
   
  // ...
  // 在生命周期中,使用TaskPool加载和解析网络数据
  this.requestByTaskPool();
}

@Concurrent
getInfoFromHttp(): string[] {
   
   
  // 从网络加载数据
  return http.request();
}

requestByTaskPool(): void {
   
   
  // 创建任务项
  let task: taskpool.Task = new taskpool.Task(this.getInfoFromHttp);
    try {
   
   
    // 执行网络加载函数
    taskpool.execute(task, taskpool.Priority.HIGH).then((res: string[]) => {
   
   
    });
  } catch (err) {
   
   
  logger.error(TAG, "failed, " + (err as BusinessError).toString());
  }
}
高频程度&收益(5满分)

5

列表场景未使用LazyForEach+组件复用+缓存列表项

类型

响应时延/完成时延/帧率

解决方法

排查使用LazyForEach的代码,确认是否有使用组件复用(@Reusable)+缓存列表项(cachedCount)。

反例
build() {
   
   
  Grid() {
   
   
    // 未使用LazyForEach+组件复用+缓存列表项
    ForEach(this.GoodDataOne, (item, index) => {
   
   
      GridItem() {
   
   
        Column() {
   
   
          Image(item.img)
            .height(item.hei)
            .width('100%')
            .objectFit(ImageFit.Fill)

          Text(item.introduce)
            .fontSize(14)
            .padding({
   
    left: 5, right: 5 })
            .margin({
   
    top: 5 })
          Row() {
   
   
            Row() {
   
   
              Text('¥')
                .fontSize(10)
                .fontColor(Color.Red)
                .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值