HarmonyOS Next如何有分帧渲染机制优化下面滑动示例代码?

@Reusable
@Component
struct ItemView {
  @State monthItem: Month = {
    month: '',
    num: 0,
    days: [],
    lunarDays: [],
    year: 0
  };
  // ...
  aboutToReuse(params: Record<string, Object>): void {
    hiTraceMeter.startTrace('reuse_' + (params.monthItem as Month).month, 1);
    this.monthItem = params.monthItem as Month;
    hiTraceMeter.finishTrace('reuse_' + (params.monthItem as Month).month, 1);
  }

  build() {
    Flex({ wrap: FlexWrap.Wrap }) {
      // ...
      // 日期信息
      ForEach(this.monthItem.days, (day: number, index: number) => {
        // ...
      }, (index: number): string => index.toString())
    }
    // ...
  }
}

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

阅读 574
1 个回答

在上面的代码中,通过组件复用,在ItemView的aboutToReuse()接口中,将一个月的数据直接设置到状态变量monthItem中,这样下面的Flex就会收到状态变量变更的消息通知,从而刷新组件中的数据。

通过displaySync中的帧回调方法,将数据拆分到每一帧中进行加载和绘制,只需要在帧回调中修改自定义子组件ItemView中加载数据的方式。

首先,需要在ItemView中第一次使用时创建displaySync对象,设置期望帧率,添加帧回调的监听,然后进行启动。

@Reusable
@Component
struct ItemView {
  // ...
  aboutToAppear(): void {
    hiTraceMeter.startTrace('appear_', 1);
    this.displaySync = displaySync.create();
    const range: ExpectedFrameRateRange = {
      expected: 120,
      min: 60,
      max: 120
    };
    this.displaySync.setExpectedFrameRateRange(range);
    this.displaySync.on('frame', () => {
      // ...
    });
    this.displaySync.start();
    allDisplaySyncArray.push(this.displaySync);
    this.temp.push(this.monthItem);
    hiTraceMeter.finishTrace('appear_', 1);
  }

  // ...
}

然后,在监听中添加更新数据的代码。这里将每个月的数据更新拆分开来,第一步用来更新月份数据和计算总的执行步骤,最后一步将计数数据清空, 方便下一次数据的写入,其余需要执行步骤的多少根据每次加载数据量会有所改变。

if (this.temp.length > 0) {
  if (this.step === 0) {
    // 第一步:放入月份数据,并计算最多需要几帧完成数据操作
    hiTraceMeter.startTrace('reuse_' + this.step, 1);
    this.month = this.temp[0].month;
    this.monthNumber = this.temp[0].num;
    this.maxStep = this.maxStep + Math.ceil(this.temp[0].days.length / this.MAX_EVERY_FRAME);
    hiTraceMeter.finishTrace('reuse_' + this.step, 1);
    this.step += 1;
  } else if (this.step === this.maxStep - 1) {
    // 最后一步:初始化部分计数数据
    this.temp = [];
    this.step = 0;
    this.maxStep = 2;
  } else {
    hiTraceMeter.startTrace('reuse_' + this.step, 1);
    const start: number = this.MAX_EVERY_FRAME * (this.step - 1);
    const end: number = (this.MAX_EVERY_FRAME * this.step) > this.temp[0].days.length ?
      this.temp[0].days.length : this.MAX_EVERY_FRAME * this.step;
    for (let i = start; i < end; i++) {
      this.days[i] = this.temp[0].days[i];
      this.lunarDays[i] = this.temp[0].lunarDays[i];
    }
    hiTraceMeter.finishTrace('reuse_' + this.step, 1);
    this.step += 1;
  }
}

最后,在aboutToReuse接口中将数据放入数组中,用于帧回调中开始执行数据更新。

aboutToReuse(params: Record<string, Object>): void {
  hiTraceMeter.startTrace('reuse_' + (params.monthItem as Month).month, 1);
  this.temp.push(params.monthItem as Month);
  hiTraceMeter.finishTrace('reuse_' + (params.monthItem as Month).month, 1);
}

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题