HarmonyOS Next中分帧渲染的具体实现是什么样的?

阅读 563
avatarAI BotBETA

HarmonyOS Next中分帧渲染的具体实现主要涉及到以下步骤和关键点:

一、分帧渲染的概念与适用场景

分帧渲染是一种优化技术,主要用于解决高负载场景下的性能问题。当页面内列表结构复杂,每个列表项包含的组件较多,导致嵌套层级较深,从而引起组件负载加重、绘制耗时增长时,转场或列表滑动时列表项会一次性加载大量数据,此时可以采用分帧渲染,将原本一帧内加载的数据分成多帧加载。

二、实现步骤

  1. 规划分帧数据

    • 开发者需要根据实际的业务逻辑、应用页面布局和数据量,提前计算规划出需要通过多少帧完成加载以及每帧具体加载的数据。
  2. 设置帧回调监听

    • 应用页面实际加载绘制时,结合页面的布局,使用帧回调监听修改状态变量或补充数据到数据结构等方式,对每一帧需要处理的渲染数据进行计算和设置。
    • 可以通过aboutToAppear()方法添加帧回调监听,并在Vsync信号变化时触发帧回调执行应用逻辑。
  3. 数据加载与渲染

    • 在帧回调中,根据规划好的数据,分帧逐步加载数据。
    • 使用ifForEach方法进行布局,避免在分帧加载数据时引起重绘。
    • 页面布局时可以给分帧渲染的外部容器组件设置宽高,避免外部容器大小改变引起重绘。
  4. 更新ViewModel并渲染UI

    • ViewModel数据改变后,驱动页面或组件执行build()方法,使用ifForEach分帧迭代渲染绘制UI并控制刷新范围。
  5. 停止帧回调监听

    • 在页面即将消失时,通过aboutToDisappear()方法停止帧回调监听。

三、示例代码

以下是一个简单的示例代码,展示了如何在HarmonyOS Next中实现分帧渲染:

@Component
export struct ProductList {
    private productData: ProductDataSource = new ProductDataSource();
    private displaySync: displaySync.DisplaySync | undefined = undefined;
    private frame: number = 1;

    aboutToAppear(): void {
        // 创建DisplaySync对象
        this.displaySync = displaySync.create();

        // 设置期望帧率
        const range: ExpectedFrameRateRange = {
            expected: 120,
            min: 60,
            max: 120
        };
        this.displaySync.setExpectedFrameRateRange(range);

        // 添加帧回调
        this.displaySync.on('frame', () => {
            if (this.frame === 1) {
                hiTraceMeter.startTrace('firstFrame', 1);
                this.productData.pushData(PRODUCT_DATA.slice(0, 2));
                this.frame += 1;
                hiTraceMeter.finishTrace('firstFrame', 1);
            } else if (this.frame === 2) {
                hiTraceMeter.startTrace('secondFrame', 2);
                this.productData.pushData(PRODUCT_DATA.slice(2, PRODUCT_DATA.length));
                hiTraceMeter.finishTrace('secondFrame', 2);
                this.frame += 1;
                this.displaySync?.stop();
            }
        });

        // 开启帧回调监听
        this.displaySync.start();
    }

    aboutToDisappear(): void {
        // 页面销毁时需要停止帧回调
        this.displaySync?.stop();
    }

    build() {
        // ... 渲染UI的代码 ...
    }
}

在上述代码中,ProductList组件在aboutToAppear()方法中创建了DisplaySync对象,并设置了期望帧率。然后添加了帧回调,在回调中根据帧号分批加载数据。最后,在aboutToDisappear()方法中停止帧回调监听。

四、注意事项

  • 分帧渲染需要开发者计算每帧中加载多少数据,操作相对复杂,因此应在必要的情况下才推荐使用。
  • 在分帧加载数据时,需要搭配合理的页面布局来避免重绘,以提高渲染性能。

通过以上步骤和示例代码,可以在HarmonyOS Next中实现分帧渲染,优化高负载场景下的性能表现。

1 个回答

在高负载场景下使用分帧渲染的关键操作是把数据拆分到每一帧中加载,但这个过程中加载新的数据时可能会将已有数据再次绘制,因此需要搭配合理的页面布局来避免重绘。可以通过if或ForEach两种方法来实现布局,两种方法的更新机制如下:

  • if更新机制是根据状态判断条件,如果分支没有变化,不会对条件渲染语句进行更新。
  • ForEach非首次渲染会检查新生成的键值是否在上次渲染中已经存在。如果键值不存在,则会创建一个新的组件;如果键值存在,则不会创建新的组件,而是直接渲染该键值所对应的组件。
    因此在分帧逐步加载数据时使用上述两种方法不会引起重绘。并且在页面布局时可以给分帧渲染的外部容器组件设置宽高,这样组件本身不会触发重新进行Measure的过程,对组件的宽高不会重新测算,避免因外部容器大小改变引起重绘,详情可参考合理使用布局。

保证页面不会重绘后,在实际开发过程中为了逐步增加页面数据,可以使用ArkTS中提供的displaySync(可变帧率)API接口,通过Vsync信号控制数据刷新的时机,来实现绘制内容帧率的控制。先通过页面UI中aboutToAppear()添加帧回调监听并开启监听,Vsync信号变化时触发帧回调执行应用逻辑,计算每帧加载的数据,改变ViewModel数据。ViewModel数据改变后驱动页面或组件执行build(),使用if或ForEach分帧迭代渲染绘制UI并控制刷新范围。最后可以在aboutToDisappear()里停止帧回调监听。

具体操作流程如下图:
image.png

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

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