harmony 鸿蒙应用性能优化常见问题解决指导

  • 2025-06-12
  • 浏览 (6)

应用性能优化常见问题解决指导

概述

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

性能规范总览目录

            
分类
                

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

性能优化规范

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

类型

响应时延/完成时延

解决方法

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

反例

const LARGE_NUMBER = 1000000;

@Entry
@Component
struct ViewA {
  @State private text: string = "";
  private count: number = 0;
  // 反例:在aboutToAppear接口中执行耗时操作,阻塞页面绘制。
  aboutToAppear() {
    // 耗时操作
    this.computeTask();
    let context = this.getUIContext().getHostContext() 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 = this.getUIContext().getHostContext() as Context;
    this.text = context.resourceManager.getStringSync($r('app.string.task_text'));
  }
}

正例

@Entry
@Component
struct ViewB {
  @State private text: string = "";
  private count: number = 0;
  private readonly DELAYED_TIME: number = 2000; // 定时器设置延时2s

  // 正例:在aboutToAppear接口中对耗时间的计算任务进行了异步处理。
  aboutToAppear() {
    // 耗时操作
    this.computeTaskAsync(); // 异步任务
    let context = this.getUIContext().getHostContext() 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 = this.getUIContext().getHostContext() as Context;
    this.text = context.resourceManager.getStringSync($r('app.string.task_text'));
  }

  // 运算任务异步处理
  private computeTaskAsync(): void {
    setTimeout(() => {
      // 这里使用setTimeout来实现异步延迟运行
      this.computeTask();
    }, this.DELAYED_TIME)
  }
}

高频程度&收益(5满分)

5

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

类型

响应时延/完成时延

解决方法

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

反例

import http from '@ohos.net.http';

async aboutToAppear() {
  // ...
  const b = await 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)。

反例

struct GoodView {
  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)
                  .baselineOffset(-4)
                Text(item.price)
                  .fontSize(16)
                  .fontColor(Color.Red)
                Text(item.numb)
                  .fontSize(10)
                  .fontColor(Color.Gray)
                  .baselineOffset(-4)
                  .margin({ left: 5 })
              }

              Image($r('app.media.photo63'))
                .width(20)
                .height(10)
                .margin({ bottom: -8 })
            }
            .width('100%')
              .justifyContent(FlexAlign.SpaceBetween)
              .padding({ left: 5, right: 5 })
              .margin({ top: 15 })
          }
          .borderRadius(10)
            .backgroundColor(Color.White)
            .clip(true)
            .width('100%')
            .height(290)
        }
      }, (item) => JSON.stringify(item))
    }
  }
}

正例

// 组件复用
@Reusable
@Component
struct GoodItems {
  @State img: Resource = $r("app.media.photo61");
  @State webImg?: string = '';
  @State hei: number = 0;
  @State introduce: string = '';
  @State price: string = '';
  @State numb: string = '';
  @LocalStorageLink('storageSimpleProp') simpleVarName: string = '';
  isOnclick: boolean = true;
  index: number = 0;
  controllerVideo: VideoController = new VideoController();

  aboutToReuse(params)
  {
    this.webImg = params.webImg;
    this.img = params.img;
    this.hei = params.hei;
    this.introduce = params.introduce;
    this.price = params.price;
    this.numb = params.numb;
  }

  build() {
    Grid(){
      // 懒加载
      LazyForEach(this.GoodDataOne, (item, index) => {
        GridItem() {
          GoodItems({
            isOnclick:item.data.isOnclick,
            img:item.data.img,
            webImg:item.data.webImg,
            hei:item.data.hei,
            introduce:item.data.introduce,
            price:item.data.price,
            numb:item.data.numb,
            index:index
          })
            .reuseId(this.CombineStr(item.type))
        }
      }, (item) => JSON.stringify(item))
    }.cachedCount(2) // 缓存列表项
  }
}

高频程度&收益(5满分)

5

Web未使用预连接,未提前初始化引擎

类型

完成时延

解决方法

在应用创建Ability的时候,在OnCreate阶段预先初始化内核,建议把引擎的初始化放在setTimeOut中。

反例

// Web组件引擎没有初始化,且沒有使用预连接
export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }
}
controller: webview.WebviewController = new webview.WebviewController();
// ...
Web({ src: 'https://www.example.com', controller: this.controller })

正例

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
    console.info("EntryAbility onCreate");
    // 在 Web 组件初始化之前,通过此接口加载 Web 引擎的动态库文件,以提高启动性能。
    setTimeout(() => {
      // 这里使用setTimeout来实现延迟运行
      web_webview.WebviewController.initializeWebEngine();
    }, 200)
    console.info("EntryAbility onCreate done");
  }
}

controller: webview.WebviewController = new webview.WebviewController();
// ...
Web({ src: 'https://www.example.com', controller: this.controller })

高频程度&收益(5满分)

5

高频接口中不要打印Trace和日志

类型

响应时延/完成时延

解决方法

排查接口onTouch、onItemDragMove、onDragMove、onDidScroll、onMouse、onVisibleAreaChange、OnAreaChange、 onActionUpdate、animator的onFrame、组件复用场景下的aboutToReuse,不建议在里面打印trace和日志。

反例

import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';

@Component
struct CounterOfOnDidScroll {
  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  build() {
    Scroll() {
      ForEach(this.arr, (item: number) => {
        Text("ListItem" + item)
          .width("100%")
          .height("100%")
      }, (item: number) => item.toString())
    }
    .width('100%')
    .height('100%')
    .onDidScroll(() => {
      hiTraceMeter.startTrace("ScrollSlide", 1002);
      // 业务逻辑
      // ...
      // 在高频接口中不建议打印Trace和日志
      hiTraceMeter.finishTrace("ScrollSlide", 1002);
    })
  }

正例

@Component
struct PositiveOfOnDidScroll {
  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  build() {
    Scroll() {
      List() {
        ForEach(this.arr, (item: number) => {
          ListItem() {
            Text("TextItem" + item)
          }.width("100%")
           .height(100)
        }, (item: number) => item.toString())
      }
      .divider({ strokeWidth: 3, color: Color.Gray })
    }
    .width('100%')
    .height('100%')
    .onDidScroll(() => {
      // 业务逻辑
      // ...
    })
  }
}

高频程度&收益(5满分)

4

组件复用里面有if语句,但是未使用reuseId

类型

完成时延/帧率

解决方法

排查使用了@Reusable的自定义组件,查看build中给是否使用了if/else或ForEach等条件渲染语句,如果使用了,需要配合reuseId一起使用。

反例

@Component
@Reusable
export struct MockComplexSubBranch {
  @State alignStyle: FlexAlign = FlexAlign.Center;

  aboutToReuse(params: Record<string, number>): void { // 缓存复用组件,更新组件的状态变量
    this.alignStyle = params.alignStyle;
  }

  build() {
    Column() {
      Column({ space: 5 }) {
        Text('ComplexSubBranch not reusable')
          .fontSize($r('app.integer.font_size_9'))
          .fontColor($r('app.color.hint_txt_color'))
          .width($r('app.string.layout_90_percent'))
      }
    }
  }
}

import { MockComplexSubBranch } from './MockComplexSubBranch';

@Component
export struct WithoutReuseId {
  @State isAlignStyleStart: boolean = true;

  build() {
    Column() {
      Button("Change FlexAlign")
        .onClick(() => {
          this.isAlignStyleStart = !this.isAlignStyleStart;
        })
      Stack() {
        if (this.isAlignStyleStart) {
          MockComplexSubBranch({ alignStyle: FlexAlign.Start }); // 未使用reuseId
        } else {
          MockComplexSubBranch({ alignStyle: FlexAlign.End });
        }
      }
    }
  }
}

正例

@Component
@Reusable
// 添加Reusable装饰器,声明组件具备可复用的能力
export struct MockComplexSubBranch {
  @State alignStyle: FlexAlign = FlexAlign.Center;

  aboutToReuse(params: Record<string, number>): void {
    this.alignStyle = params.alignStyle;
  }

  build() {
    Column() {
      Column({ space: 5 }) {
        Text('ComplexSubBranch reusable')
          .fontSize($r('app.integer.font_size_9'))
          .fontColor($r('app.color.hint_txt_color'))
          .width($r('app.string.layout_90_percent'))
      }
    }
  }
}

import { MockComplexReusableSubBranch } from './MockComplexReusableSubBranch';

@Component
export struct WithReuseId {
  @State isAlignStyleStart: boolean = true;

  build() {
    Column() {
      Button("Change FlexAlign")
        .onClick(() => {
          this.isAlignStyleStart = !this.isAlignStyleStart;
        })
      Stack() {
        if (this.isAlignStyleStart) {
          MockComplexSubBranch({ alignStyle: FlexAlign.Start }).reuseId("MockComplexSubBranchStart"); // 使用reuseId标识
        } else {
          MockComplexSubBranch({ alignStyle: FlexAlign.End }).reuseId("MockComplexSubBranchEnd");
        }
      }
    }
  }
}

高频程度&收益(5满分)

4

不建议使用@Prop装饰器

类型

响应时延/完成时延

解决方法

全局搜索@Prop并且替换。

反例

@Observed
class Book {
  public c: number = 0;

  constructor(c: number) {
    this.c = c;
  }
}

@Component
struct PropChild {
  @Prop testNum: Book; // @Prop装饰状态变量会深拷贝

  build() {
    Text(`PropChild testNum ${this.testNum.c}`)
  }
}

@Entry
@Component
struct Parent1 {
  @State testNum: Book[] = [new Book(1)];

  build() {
    Column() {
      Text(`Parent testNum ${this.testNum[0].c}`)
        .onClick(() => {
          this.testNum[0].c += 1;
        })
      // PropChild没有改变@Prop testNum: Book的值,所以这时最优的选择是使用@ObjectLink
      PropChild({ testNum: this.testNum[0] })
    }
  }
}

正例

@Observed
class Book {
  public c: number = 0;

  constructor(c: number) {
    this.c = c;
  }
}

@Component
struct PropChild {
  @ObjectLink testNum: Book; // @ObjectLink装饰状态变量不会深拷贝

  build() {
    Text(`PropChild testNum ${this.testNum.c}`)
  }
}

@Entry
@Component
struct Parent2 {
  @State testNum: Book[] = [new Book(1)];

  build() {
    Column() {
      Text(`Parent testNum ${this.testNum[0].c}`)
        .onClick(() => {
          this.testNum[0].c += 1;
        })
      // 当子组件不需要发生本地改变时,优先使用 @ObjectLink,因为@Prop是会深拷贝数据,具有拷贝的性能开销,所以这个时候@ObjectLink是比@Link和 @Prop更优的选择
      PropChild({ testNum: this.testNum[0] })
    }
  }
}

高频程度&收益(5满分)

4

避免在ResourceManager的getXXXSync接口入参中直接使用资源信息

类型

响应时延/完成时延

解决方法

排查ResourceManager.getXXXSync接口,查看入参时需要使用getStringSync($r(‘app.media.icon’).id)的形式, 如果未使用需要整改。

反例

this.context.resourceManager.getStringSync($r('app.string.test'));

正例

this.context.resourceManager.getStringSync($r('app.string.test').id);

高频程度&收益(5满分)

3

展示用的自定义组件(数据从父组件中获取,无独立数据处理)使用@Builder替换

类型

响应时延/完成时延

解决方法

审视@Component标记的自定义组件,如果里面没有独立的生命周期处理逻辑,数据由父组件传递,建议@Builder替代。

反例

@Entry
@Component
struct CEMineButtomView {
  build() {
    View();
  }
}

@Component
export struct ViewA {
  build() {
    Row() {
      Text('- 到底了 -')
        .fontSize(12)
        .fontColor($r("app.color.color_1"))
    }.justifyContent(FlexAlign.Center)
     .width('100%')
     .height(51)
     .padding({ bottom: 21 })
  }
}

正例

@Builder
function viewB() {
  Row() {
    Text('- 到底了 -').fontSize(12)
      .fontColor($r("app.color.color_1"))
  }
  .justifyContent(FlexAlign.Center)
    .width('100%')
    .height(51)
    .padding({ bottom: 21 })
}

@Entry
@Component
struct CEMineButtomView {
  build() {
    Column(){
      viewB()
    }.width('100%')
  }
}

高频程度&收益(5满分)

3

删除无具体逻辑的生命周期,ArkUI的函数回调等,删除冗余堵塞日志打印

类型

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

解决方法

排查所有的aboutToAppear、aboutToDisappear等生命周期函数,排查ArkUI的回调函数,如果函数中无具体业务逻辑, 例如只打印了日志,删除函数回调。

反例

import promptAction from '@ohos.promptAction';

@Entry
@Component
struct ViewA {
  aboutToAppear(): void {
    hilog.info(0x101, 'tag', 'Index.ets aboutToAppear');  // 无具体业务逻辑的日志
  }

  aboutToDisappear(): void{
    hilog.info(0x101, 'tag', 'Index.ets aboutToDisappear'); // 无具体业务逻辑的日志
  }

  /**
   * 弹窗函数
   */
  showToast() {
    this.getUIContext().getPromptAction().showToast({
      message: $r('app.string.water_mark_toast_message')
    })
  }

  build() {
    Column(){
      Text('测试一下')
        .onClick(() => {
          this.showToast(); // 有业务逻辑的方法
        })
    }.width('100%')
  }
}

正例

import promptAction from '@ohos.promptAction';

@Entry
@Component
struct ViewB {
  /**
   * 弹窗函数
   */
  showToast() {
    this.getUIContext().getPromptAction().showToast({
      message: $r('app.string.water_mark_toast_message')
    })
  }

  build() {
    Column(){
      Text('测试一下')
        .onClick(() => {
          this.showToast(); // 有业务逻辑的方法
        })
    }.width('100%')
  }
}

高频程度&收益(5满分)

3

删除未关联组件的状态变量装饰器

类型

响应时延/完成时延

解决方法

排查全局的状态变量装饰器,如果变量未关联组件,删除装饰器。

反例

@Component
struct ComponentA {
  @State message: string = 'Hello World';
  @State textColor: string|Color = '#007DFF';
  @State bgcolor: string|Color = '#ffffff'; // 变量bgcolor是没有关联组件的
  @State selectColor: string|Color = '#007DFF'; // 变量selectColor是没有关联组件的

  build() {
    Column(){
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.textColor)
    }
  }
}

正例

@Component
struct ComponentB {
  @State message: string = 'Hello World';
  @State textColor: string|Color = '#007DFF';
  bgcolor: string|Color = '#ffffff'; // 变量bgcolor是有关联组件的
  selectColor: string|Color = '#007DFF'; // 变量selectColor是有关联组件的

  build() {
    Column(){
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.selectColor)
        .backgroundColor(this.bgcolor)
    }
  }
}

高频程度&收益(5满分)

2

crypto-js性能差

类型

帧率

解决方法

排查buffer.from关键字,加密建议使用原生的cryptoFramework,然后将buffer替换为base64helper,性能提升10倍以上, 且数据量越大越明显。

反例

new Uint8Array(buffer.from(str,'base64').buffer);

正例

let that = new util.Base64Helper();
let result = that.decodeSync(str);

高频程度&收益(5满分)

2

不建议使用Marquee组件

类型

响应时延/完成时延

解决方法

排查Marquee关键字,使用Text的跑马灯模式(TextOverflow.MARQUEE)替代。

反例

struct ViewA {
  build() {
    Column() {
      Marquee({
        start: this.start,
        step: this.step,
        loop: this.loop,
        fromStart: this.fromStart,
        src: this.src
      })
        .width(360)
        .height(80)
        .fontColor('#FFFFFF')
        .fontSize(48)
        .fontWeight(700)
        .backgroundColor('#182431')
        .margin({ bottom: 40 })
        .onStart(() => {
          console.info('Marquee animation complete onStart');
        })
        .onBounce(() => {
          console.info('Marquee animation complete onBounce');
        })
        .onFinish(() => {
          console.info('Marquee animation complete onFinish');
        })
    }.width("100%")
  }
}

正例

struct ViewB {
  build(){
    Column(){
      Text(reply.user)
        .maxLines(1)
        .textOverflow({ overflow: TextOverflow.MARQUEE }) // 跑马灯模式
        .width("30%")
    }.width("100%")
  }
}

高频程度&收益(5满分)

1

不能使用函数作为ArkUI组件的属性和组件复用的自定义组件的入参

类型

完成时延

解决方法

查看属性是否有xx()函数写法,确认函数/方法中是否有耗时操作,替换成变量。

反例

struct ViewA {
  build() {
    Column() {
      List() {
        LazyForEach(this.data, (item: string) => {
          ListItem() {
            // 此处sum参数是函数获取的,每次组件复用都会重复触发此函数的调用
            ChildComponent({ desc: item, sum: this.count() })
          }.width('100%').height(100)
        }, (item: string) => item)
      }
    }
  }
}

正例

struct ViewB {
  @State sum: number = 0;

  aboutToAppear(): void {
    this.sum = this.count();
  }

  build() {
    Column() {
      List() {
        LazyForEach(this.data, (item: string) => {
          ListItem() {
            ChildComponent({ desc: item, sum: this.sum })
          }.width('100%').height(100)
        }, (item: string) => item)
      }
    }
  }
}

高频程度&收益(5满分)

1

不建议使用.linearGradient颜色渐变属性

类型

完成时延

解决方法

排查linearGradient关键字,可以使用图片代替。

反例

Row()
  .linearGradient({
    angle: 90,
    colors: [[0xff0000, 0.0], [0x0000ff, 0.3], [0xffff00, 1.0]]
  })

正例

Image($r('app.media.gradient_color'))

高频程度&收益(5满分)

1

不要在for/while循环中执行耗时操作

类型

完成时延/帧率

解决方法

排查for/while循环,查看里面是否有打印日志或者Trace。

反例

@Component
struct ViewA {
  @State message: string = "";

  build() {
    Column() {
      Button('点击打印日志').onClick(() => {
        for (let i = 0; i < 10; i++) {
          console.info(this.message);
        }
      })
    }
  }
}

正例

@Component
struct ViewB {
  @State message: string = "";

  build() {
    Column() {
      Button('点击打印日志').onClick(() => {
        let logMessage: string = this.message;
        for (let i = 0; i < 10; i++) {
          console.info(logMessage); // 状态变量需先赋值,再调用会优化性能
        }
      })
    }
  }
}

高频程度&收益(5满分)

1

变量初值不建议设置为undefined,需进行默认初始化

类型

完成时延

解决方法

例如number设置为0,string设置为空字符串等,这样在使用过程中更不需要增加额外判空。 排查类中的变量,看看是否有初始化为undefined。

反例

@State channels?: Channels[] = undefined;

正例

@State channels?: Channels[] = [];

高频程度&收益(5满分)

1

你可能感兴趣的鸿蒙文章

harmony 鸿蒙延迟加载lazy-import使用指导

harmony 鸿蒙性能

harmony 鸿蒙应用程序动效能力实践

harmony 鸿蒙应用性能分析工具CPU Profiler的使用指导

harmony 鸿蒙应用性能问题分析指导

harmony 鸿蒙应用开发性能优化入门引导

harmony 鸿蒙页面布局检查器ArkUI Inspector使用指导

harmony 鸿蒙性能提升的其他方法

harmony 鸿蒙音画同步最佳实践

harmony 鸿蒙避免在滑动场景的高频回调接口中处理耗时操作

0  赞