目录

Requesting Frame Rates for UI Components

If you need to draw and update UI content at an independent frame rate, you can use DisplaySync. The frame rate for drawing content in an app can be controlled by a DisplaySync instance. For details, see @ohos.graphics.displaySync (Variable Frame Rate).

How to Develop

The following example changes the font size of a text component at different frame rates to simulate the effect of different UI drawing frame rates.

  1. Import the DisplaySync module.

    import { displaySync } from '@kit.ArkGraphics2D';
  2. Define and create a DisplaySync instance.

    @Entry
    @Component
    struct Index {
      // ...
    
      private backDisplaySyncSlow: displaySync.DisplaySync | undefined = undefined;
      private backDisplaySyncFast: displaySync.DisplaySync | undefined = undefined;
      // ...
    }
  3. Define two <Text> components.

    @State drawFirstSize: number = 25;
    @State drawSecondSize: number = 25;
    
    // ...
    
    @Builder
    doSomeRenderFirst() {
      Text('30')
        .fontSize(this.drawFirstSize)
    }
    
    @Builder
    doSomeRenderSecond() {
      Text('60')
        .fontSize(this.drawSecondSize)
    }
  4. Set the expected frame rate range and register a subscription function through the DisplaySync instance.

    The subscription function runs in the UI main thread. To avoid adverse impact on the performance, time-consuming operations related to the UI thread should not run in the subscription function.

    CreateDisplaySyncSlow() {
      let range: ExpectedFrameRateRange = {
        expected: 30,
        min: 0,
        max: 120
      };
    
      let draw30 = (intervalInfo: displaySync.IntervalInfo) => {
        if (this.isBigger_30) {
          this.drawFirstSize += 1;
          if (this.drawFirstSize > 150) {
            this.isBigger_30 = false;
          }
        } else {
          this.drawFirstSize -= 1;
          if (this.drawFirstSize < 25) {
            this.isBigger_30 = true;
          }
        }
      };
    
      this.backDisplaySyncSlow = displaySync.create();
      this.backDisplaySyncSlow.setExpectedFrameRateRange(range);
      this.backDisplaySyncSlow.on("frame", draw30);
    }
  5. Start the per-frame callback.

    Button('Start')
      .id('CustomDrawStart')
      .fontSize(14)
      .fontWeight(500)
      .margin({ bottom: 10, left: 5 })
      .fontColor(Color.White)
      .onClick((): void => {
        if (this.backDisplaySyncSlow == undefined) {
          this.CreateDisplaySyncSlow();
        }
        if (this.backDisplaySyncFast == undefined) {
          this.CreateDisplaySyncFast();
        }
        if (this.backDisplaySyncSlow) {
          this.backDisplaySyncSlow.start();
        }
        if (this.backDisplaySyncFast) {
          this.backDisplaySyncFast.start();
        }
      })
      .width('20%')
      .height(40)
      .shadow(ShadowStyle.OUTER_DEFAULT_LG)

    After start() is called, the stop() API must be performed and the DisplaySync instance must be set to null in the aboutToDisappear function to avoid memory leaks.

    aboutToDisappear() {
      if (this.backDisplaySyncSlow) {
        this.backDisplaySyncSlow.stop();
        this.backDisplaySyncSlow = undefined;
      }
      if (this.backDisplaySyncFast) {
        this.backDisplaySyncFast.stop();
        this.backDisplaySyncFast = undefined;
      }
    }
  6. Stop callback for each frame.

    Button('Stop')
      .id('CustomDrawStop')
      .fontSize(14)
      .fontWeight(500)
      .margin({ bottom: 10, left: 5 })
      .fontColor(Color.White)
      .onClick((): void => {
        if (this.backDisplaySyncSlow) {
          this.backDisplaySyncSlow.stop();
        }
        if (this.backDisplaySyncFast) {
          this.backDisplaySyncFast.stop();
        }
      })
      .width('20%')
      .height(40)
      .shadow(ShadowStyle.OUTER_DEFAULT_LG)