Requesting Frame Rates for Custom Content
When you use native APIs to develop an application based on the <XComponent>, you can request an independent frame rate for custom content in scenarios such as gaming and custom UI framework interconnection.
Available APIs
Name | Description |
---|---|
OH_NativeXComponent_SetExpectedFrameRateRange (OH_NativeXComponent *component, OH_NativeXComponent_ExpectedRateRange *range) | Sets the expected frame rate range. |
OH_NativeXComponent_RegisterOnFrameCallback (OH_NativeXComponent *component, OH_NativeXComponent_OnFrameCallback *callback) | Registers the display update callback and enables the callback for each frame. |
OH_NativeXComponent_UnRegisterOnFrameCallback (OH_NativeXComponent *component) | Deregisters the display update callback and disables the callback for each frame. |
How to Develop
NOTE
This section draws a graphic through the native Drawing module and presents it using the native Window module. For details, see Using Drawing to Draw and Display Graphics.
-
Define an ArkTS API file and name it XComponentContext.ts, which is used to connect to the native layer.
export default interface XComponentContext { register(): void; unregister(): void; };
-
Define a demo page, which contains two <XComponents>.
@Entry @Component struct Index { private xComponentContext1: XComponentContext | undefined = undefined; private xComponentContext2: XComponentContext | undefined = undefined; Row() { XComponent({ id: 'xcomponentId_30', type: 'surface', libraryname: 'entry' }) .onLoad((xComponentContext) => { this.xComponentContext1 = xComponentContext as XComponentContext; }).width('832px') }.height('40%') Row() { XComponent({ id: 'xcomponentId_120', type: 'surface', libraryname: 'entry' }) .onLoad((xComponentContext) => { this.xComponentContext2 = xComponentContext as XComponentContext; }).width('832px')// Multiples of 64 }.height('40%') }
-
Configure the frame rate and register the callback function at the native layer.
static void TestCallback(OH_NativeXComponent *component, uint64_t timestamp, uint64_t targetTimestamp) // Define the callback function for each frame. { // ... // Obtain the surface size of the XComponent. int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, nativeWindow, &width, &height); if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) { render->Prepare(); render->Create(); if (id == "xcomponentId_30") { // When the frame rate is 30 Hz, the frame moves by 16 pixels at a time. render->ConstructPath(16, 16, render->defaultOffsetY); } if (id == "xcomponentId_120") { // When the frame rate is 120 Hz, the frame moves by 4 pixels at a time. render->ConstructPath(4, 4, render->defaultOffsetY); } // ... } }
NOTE
- The callback 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 callback function.
- After the instance calls NapiRegister, it must call NapiUnregister when it no longer needs to control the frame rate, so as to avoid memory leakage.
void SampleXComponent::RegisterOnFrameCallback(OH_NativeXComponent *nativeXComponent) { OH_NativeXComponent_RegisterOnFrameCallback(nativeXComponent, TestCallback); // Register the callback function and enable callback for each frame. } napi_value SampleXComponent::NapiRegister(napi_env env, napi_callback_info info) { // ... render->RegisterOnFrameCallback(nativeXComponent); // Register the callback function and enable callback for each frame at the TS layer. // ... } napi_value SampleXComponent::NapiUnregister(napi_env env, napi_callback_info info) { // ... The OH_NativeXComponent_UnregisterOnFrameCallback(nativeXComponent); // Deregister the callback function for each frame at the TS layer. // ... }
-
Register and deregister the callback function for each frame at the TS layer.
Row() { Button('Start') .id('Start') .fontSize(14) .fontWeight(500) .margin({ bottom: 20, right: 6, left: 6 }) .onClick(() => { if (this.xComponentContext1) { this.xComponentContext1.register(); } if (this.xComponentContext2) { this.xComponentContext2.register(); } }) .width('30%') .height(40) .shadow(ShadowStyle.OUTER_DEFAULT_LG) Button('Stop') .id('Stop') .fontSize(14) .fontWeight(500) .margin({ bottom: 20, left: 6 }) .onClick(() => { if (this.xComponentContext1) { this.xComponentContext1.unregister(); } if (this.xComponentContext2) { this.xComponentContext2.unregister(); } }) .width('30%') .height(40) .shadow(ShadowStyle.OUTER_DEFAULT_LG) }