Requesting Frame Rates for UI Components

If you want to draw and update a UI component at an independent frame rate, you can call the APIs provided by the DisplaySync module. For details, see @ohos.graphics.displaySync (Variable Frame Rate).

How to Develop

This section describes how to use different frame rates to change the font size of the <Text> component. This operation simulates the effect of different frame rates on the UI components.

  1. Import the DisplaySync module.

    import displaySync from '@ohos.graphics.displaySync';
    
  2. Define and create a DisplaySync instance.

    @Entry
    @Component
    struct Index {
      // Define two DisplaySync variables, which are not initialized.
      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.

    NOTE

    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 = { // Create and configure the frame rate parameter.
          expected: 30, // Set the expected frame rate to 30 Hz.
          min: 0, // Set the frame rate range.
          max: 120 // Set the frame rate range.
        };
    
        let draw30 = (intervalInfo: displaySync.IntervalInfo) => { // Subscription function. The font size changes from 25 to 150.
          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 (); // Create a DisplaySync instance.
        this.backDisplaySyncSlow.setExpectedFrameRateRange(range); // Set the frame rate range.
        this.backDisplaySyncSlow.on("frame", draw30); // Subscribe to the frame event and register the subscription function.
    }
    
  5. Start callback for each frame.

    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)
    

    NOTE

    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 leakage.

    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)
    

Sample Code

import displaySync from '@ohos.graphics.displaySync';

@Entry
@Component
struct Index {
  @State drawFirstSize: number = 25;
  @State drawSecondSize: number = 25;
  private backDisplaySyncSlow: displaySync.DisplaySync | undefined = undefined;
  private backDisplaySyncFast: displaySync.DisplaySync | undefined = undefined;
  private isBigger_30:boolean = true;
  private isBigger_60:boolean = true;

  @Builder doSomeRenderFirst() {
    Text('30')
      .fontSize(this.drawFirstSize)
  }

  @Builder doSomeRenderSecond() {
    Text('60')
      .fontSize(this.drawSecondSize)
  }

  CreateDisplaySyncSlow() {
    // Define the expected frame rate range.
    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 (); // Create a DisplaySync instance.
    this.backDisplaySyncSlow.setExpectedFrameRateRange(range); // Set the frame rate range.
    this.backDisplaySyncSlow.on("frame", draw30); // Subscribe to the frame event and register the subscription function.
  }

  CreateDisplaySyncFast() {
    // Define the expected frame rate range.
    let range : ExpectedFrameRateRange = {
      expected: 60,
      min: 0,
      max: 120
    };

    let draw60 = (intervalInfo: displaySync.IntervalInfo) => {
      if (this.isBigger_60) {
        this.drawSecondSize += 1;
        if (this.drawSecondSize > 150) {
          this.isBigger_60 = false;
        }
      } else {
        this.drawSecondSize -= 1;
        if (this.drawSecondSize < 25) {
          this.isBigger_60 = true;
        }
      }

    };

    this.backDisplaySyncFast= displaySync.create(); // Create a DisplaySync instance.
    this.backDisplaySyncFast.setExpectedFrameRateRange(range); // Set the frame rate.
    this.backDisplaySyncFast.on("frame", draw60); // Subscribe to the frame event and register the subscription function.
  }

  aboutToDisappear() {
    if (this.backDisplaySyncSlow) {
      this.backDisplaySyncSlow.stop (); // DisplaySync disabled.
      this.backDisplaySyncSlow = undefined; // Set the DisplaySync instance to null.
    }
    if (this.backDisplaySyncFast) {
      this.backDisplaySyncFast.stop(); // DisplaySync disabled.
      this.backDisplaySyncFast = undefined; // Set the DisplaySync instance to null.
    }
  }

  build() {
    Column() {
      Row() {
        this.doSomeRenderFirst();
      }
      .height('40%')

      Row() {
        this.doSomeRenderSecond();
      }
      .height('40%')

      Row() {
        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 (); // DisplaySync enabled.
            }
            if (this.backDisplaySyncFast) {
              this.backDisplaySyncFast.start(); // DisplaySync enabled.
            }
          })
          .width('20%')
          .height(40)
          .shadow(ShadowStyle.OUTER_DEFAULT_LG)

        Button('Stop')
          .id('CustomDrawStop')
          .fontSize(14)
          .fontWeight(500)
          .margin({ bottom: 10, left: 5 })
          .fontColor(Color.White)
          .onClick((): void => {
            if (this.backDisplaySyncSlow) {
              this.backDisplaySyncSlow.stop (); // DisplaySync disabled.
            }
            if (this.backDisplaySyncFast) {
              this.backDisplaySyncFast.stop(); // DisplaySync disabled.
            }
          })
          .width('20%')
          .height(40)
          .shadow(ShadowStyle.OUTER_DEFAULT_LG)
      }
      .width('100%')
      .justifyContent(FlexAlign.Center)
      .shadow(ShadowStyle.OUTER_DEFAULT_SM)
      .alignItems(VerticalAlign.Bottom)
      .layoutWeight(1)
    }
  }
}