1e41f4b71Sopenharmony_ci# Embedding ArkTS Components 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci 4e41f4b71Sopenharmony_ciArkUI on the native side offers a subset of ArkTS features, excluding certain capabilities such as declarative UI syntax, custom struct components, and advanced UI components. 5e41f4b71Sopenharmony_ci 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciFor scenarios requiring ArkTS-specific features, ArkUI provides a mechanism to embed ArkTS components using [ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md). This involves encapsulating ArkTS components and passing them to the native side, where they are converted into **ArkUI_NodeHandle** objects through the [OH_ArkUI_GetNodeHandleFromNapiValue](../reference/apis-arkui/_ark_u_i___native_module.md#oh_arkui_getnodehandlefromnapivalue) API for component mounting. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci 10e41f4b71Sopenharmony_ci> **NOTE** 11e41f4b71Sopenharmony_ci> 12e41f4b71Sopenharmony_ci> - **ArkUI_NodeHandle** objects obtained from **OH_ArkUI_GetNodeHandleFromNapiValue** are for child component parameters only, such as the second parameter of the [addChild](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addchild) API. Using such objects in other scenarios, such as setting attributes with [setAttribute](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#setattribute), will not take effect and will return an error code. 13e41f4b71Sopenharmony_ci> 14e41f4b71Sopenharmony_ci> - To modify ArkTS components on the native side, construct update data using Node-APIs, and then call the [update](../reference/apis-arkui/js-apis-arkui-ComponentContent.md#update) API of **ComponentContent**. 15e41f4b71Sopenharmony_ci> 16e41f4b71Sopenharmony_ci> - During the process of [building custom components](ndk-build-custom-components.md), functions such as **measureNode** cannot be used to call components within the ArkTS module. 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ciThe following example introduces the ArkTS **Refresh** component based on the [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md) section. 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci**Figure 1** Mounting a text list to a Refresh component 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci1. Register the ArkTS component creation function to the native side for it to call, and use the **ComponentContent** capability to encapsulate the creation function. 28e41f4b71Sopenharmony_ci ```ts 29e41f4b71Sopenharmony_ci // MixedModule.ets 30e41f4b71Sopenharmony_ci // Create ArkTS components using the ComponentContent capability. 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci import { NodeContent, UIContext, RefreshModifier, ComponentContent } from '@kit.ArkUI'; 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ci // Define the data object for interaction between the native side and ArkTS. 35e41f4b71Sopenharmony_ci interface NativeRefreshAttribute { 36e41f4b71Sopenharmony_ci isRefreshing: boolean; 37e41f4b71Sopenharmony_ci width?: number; 38e41f4b71Sopenharmony_ci height?: number; 39e41f4b71Sopenharmony_ci backgroundColor?: number; 40e41f4b71Sopenharmony_ci refreshOffset?: number; 41e41f4b71Sopenharmony_ci pullToRefresh?: boolean 42e41f4b71Sopenharmony_ci onRefreshing?: () => void; 43e41f4b71Sopenharmony_ci onOffsetChange?: (offset: number) => void; 44e41f4b71Sopenharmony_ci } 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci // Define the format of the input parameters for the @Builder function. 47e41f4b71Sopenharmony_ci interface RefreshAttribute { 48e41f4b71Sopenharmony_ci isRefreshing: boolean; 49e41f4b71Sopenharmony_ci // Optimize attribute settings for performance with Modifier. 50e41f4b71Sopenharmony_ci modifier?: RefreshModifier; 51e41f4b71Sopenharmony_ci slot?: NodeContent; 52e41f4b71Sopenharmony_ci onRefreshing?: () => void; 53e41f4b71Sopenharmony_ci onOffsetChange?: (offset: number) => void; 54e41f4b71Sopenharmony_ci } 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci // ComponentContent encapsulates the ArkTS component dependency on the global @Builder function. You can nest @Component decorated custom components within the @Builder function when needed. 57e41f4b71Sopenharmony_ci // The @Builder function provides a way of passing parameters, making it convenient to update parameters later through the update API of ComponentContent. 58e41f4b71Sopenharmony_ci @Builder 59e41f4b71Sopenharmony_ci function mixedRefresh(attribute: RefreshAttribute) { 60e41f4b71Sopenharmony_ci Refresh({ refreshing: attribute.isRefreshing }) { 61e41f4b71Sopenharmony_ci // As a container component, Refresh needs to use the ContentSlot mechanism to reserve a place for child components. 62e41f4b71Sopenharmony_ci ContentSlot(attribute.slot) 63e41f4b71Sopenharmony_ci }.attributeModifier(attribute.modifier) 64e41f4b71Sopenharmony_ci .onRefreshing(() => { 65e41f4b71Sopenharmony_ci console.info("on onRefreshing"); 66e41f4b71Sopenharmony_ci if (attribute.onRefreshing) { 67e41f4b71Sopenharmony_ci console.info("on native onRefreshing"); 68e41f4b71Sopenharmony_ci attribute.onRefreshing(); 69e41f4b71Sopenharmony_ci } 70e41f4b71Sopenharmony_ci }) 71e41f4b71Sopenharmony_ci .onOffsetChange((value: number) => { 72e41f4b71Sopenharmony_ci console.info("on offset change: " + value); 73e41f4b71Sopenharmony_ci if (attribute.onOffsetChange) { 74e41f4b71Sopenharmony_ci console.info("on native onOffsetChange"); 75e41f4b71Sopenharmony_ci attribute.onOffsetChange(value); 76e41f4b71Sopenharmony_ci } 77e41f4b71Sopenharmony_ci }) 78e41f4b71Sopenharmony_ci } 79e41f4b71Sopenharmony_ci 80e41f4b71Sopenharmony_ci // Define the return value of the creation function for interaction between the ArkTS side and the native side. 81e41f4b71Sopenharmony_ci interface MixedModuleResult { 82e41f4b71Sopenharmony_ci // Define the encapsulated object for the Refresh construction function, used by the native side to convert to an ArkUI_NodeHandle object. 83e41f4b71Sopenharmony_ci content?: ComponentContent<RefreshAttribute>; 84e41f4b71Sopenharmony_ci // As a container component, Refresh needs to use the ContentSlot mechanism to mount child components from the native side. 85e41f4b71Sopenharmony_ci childSlot?: NodeContent; 86e41f4b71Sopenharmony_ci } 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ci // Provide an entry function for creating ArkTS components. 89e41f4b71Sopenharmony_ci export function createMixedRefresh(value: NativeRefreshAttribute): MixedModuleResult { 90e41f4b71Sopenharmony_ci console.info("createMixedRefresh"); 91e41f4b71Sopenharmony_ci // Use the AppStorage object to maintain the UI context object when the ability starts. 92e41f4b71Sopenharmony_ci let uiContent = AppStorage.get<UIContext>("context"); 93e41f4b71Sopenharmony_ci let modifier = new RefreshModifier(); 94e41f4b71Sopenharmony_ci if (value.width) { 95e41f4b71Sopenharmony_ci modifier.width(value.width) 96e41f4b71Sopenharmony_ci } 97e41f4b71Sopenharmony_ci if (value.height) { 98e41f4b71Sopenharmony_ci modifier.height(value.height) 99e41f4b71Sopenharmony_ci } 100e41f4b71Sopenharmony_ci if (value.backgroundColor) { 101e41f4b71Sopenharmony_ci modifier.backgroundColor(value.backgroundColor) 102e41f4b71Sopenharmony_ci } 103e41f4b71Sopenharmony_ci if (value.pullToRefresh) { 104e41f4b71Sopenharmony_ci modifier.pullToRefresh(value.pullToRefresh) 105e41f4b71Sopenharmony_ci } 106e41f4b71Sopenharmony_ci if (value.refreshOffset) { 107e41f4b71Sopenharmony_ci modifier.refreshOffset(value.refreshOffset) 108e41f4b71Sopenharmony_ci } 109e41f4b71Sopenharmony_ci // Create a NodeContent slot object for mounting Refresh child components. 110e41f4b71Sopenharmony_ci let nodeSlot = new NodeContent(); 111e41f4b71Sopenharmony_ci // Create the Refresh component using ComponentContent and encapsulate it. 112e41f4b71Sopenharmony_ci let content = new ComponentContent<RefreshAttribute>(uiContent!, wrapBuilder<[RefreshAttribute]>(mixedRefresh), 113e41f4b71Sopenharmony_ci { 114e41f4b71Sopenharmony_ci isRefreshing: value.isRefreshing, 115e41f4b71Sopenharmony_ci modifier: modifier, 116e41f4b71Sopenharmony_ci slot: nodeSlot, 117e41f4b71Sopenharmony_ci onRefreshing: value.onRefreshing, 118e41f4b71Sopenharmony_ci onOffsetChange: value.onOffsetChange 119e41f4b71Sopenharmony_ci }); 120e41f4b71Sopenharmony_ci // Pass the encapsulated object of the Refresh component and its child component slot object to the native side. 121e41f4b71Sopenharmony_ci return { content: content, childSlot: nodeSlot }; 122e41f4b71Sopenharmony_ci } 123e41f4b71Sopenharmony_ci 124e41f4b71Sopenharmony_ci // Define the update function for the Refresh component for updating by the native side. 125e41f4b71Sopenharmony_ci // In the update scenario, you need to return the encapsulated object of the Refresh component and its child component slot object to prevent the component from being re-created. 126e41f4b71Sopenharmony_ci export function updateMixedRefresh(refresh: ComponentContent<RefreshAttribute>, childSlot: NodeContent, 127e41f4b71Sopenharmony_ci value: NativeRefreshAttribute): void { 128e41f4b71Sopenharmony_ci let modifier = new RefreshModifier(); 129e41f4b71Sopenharmony_ci if (value.width) { 130e41f4b71Sopenharmony_ci modifier.width(value.width) 131e41f4b71Sopenharmony_ci } 132e41f4b71Sopenharmony_ci if (value.height) { 133e41f4b71Sopenharmony_ci modifier.height(value.height) 134e41f4b71Sopenharmony_ci } 135e41f4b71Sopenharmony_ci if (value.backgroundColor) { 136e41f4b71Sopenharmony_ci modifier.backgroundColor(value.backgroundColor) 137e41f4b71Sopenharmony_ci } 138e41f4b71Sopenharmony_ci if (value.pullToRefresh) { 139e41f4b71Sopenharmony_ci modifier.pullToRefresh(value.pullToRefresh) 140e41f4b71Sopenharmony_ci } 141e41f4b71Sopenharmony_ci if (value.refreshOffset) { 142e41f4b71Sopenharmony_ci modifier.refreshOffset(value.refreshOffset) 143e41f4b71Sopenharmony_ci } 144e41f4b71Sopenharmony_ci // Call the update API of ComponentContent to update. 145e41f4b71Sopenharmony_ci refresh.update({ 146e41f4b71Sopenharmony_ci isRefreshing: value.isRefreshing, 147e41f4b71Sopenharmony_ci modifier: modifier, 148e41f4b71Sopenharmony_ci slot: childSlot, 149e41f4b71Sopenharmony_ci onRefreshing: value.onRefreshing, 150e41f4b71Sopenharmony_ci onOffsetChange: value.onOffsetChange 151e41f4b71Sopenharmony_ci }) 152e41f4b71Sopenharmony_ci } 153e41f4b71Sopenharmony_ci 154e41f4b71Sopenharmony_ci ``` 155e41f4b71Sopenharmony_ci 156e41f4b71Sopenharmony_ci2. Register the creation and update functions with the native side. 157e41f4b71Sopenharmony_ci ```ts 158e41f4b71Sopenharmony_ci // entry.ets 159e41f4b71Sopenharmony_ci import nativeNode from 'libentry.so'; 160e41f4b71Sopenharmony_ci import { NodeContent } from '@kit.ArkUI'; 161e41f4b71Sopenharmony_ci import { createMixedRefresh, updateMixedRefresh } from './MixedModule' 162e41f4b71Sopenharmony_ci 163e41f4b71Sopenharmony_ci @Entry 164e41f4b71Sopenharmony_ci @Component 165e41f4b71Sopenharmony_ci struct Index { 166e41f4b71Sopenharmony_ci private rootSlot = new NodeContent(); 167e41f4b71Sopenharmony_ci @State @Watch('changeNativeFlag') showNative: boolean = false; 168e41f4b71Sopenharmony_ci 169e41f4b71Sopenharmony_ci aboutToAppear(): void { 170e41f4b71Sopenharmony_ci // Set the UI context. 171e41f4b71Sopenharmony_ci AppStorage.setOrCreate<UIContext>("context", this.getUIContext()); 172e41f4b71Sopenharmony_ci // Set the builder function for mixed mode. 173e41f4b71Sopenharmony_ci nativeNode.registerCreateMixedRefreshNode(createMixedRefresh); 174e41f4b71Sopenharmony_ci nativeNode.registerUpdateMixedRefreshNode(updateMixedRefresh); 175e41f4b71Sopenharmony_ci } 176e41f4b71Sopenharmony_ci 177e41f4b71Sopenharmony_ci changeNativeFlag(): void { 178e41f4b71Sopenharmony_ci if (this.showNative) { 179e41f4b71Sopenharmony_ci // Create and mount the NativeModule component. 180e41f4b71Sopenharmony_ci nativeNode.createNativeRoot(this.rootSlot) 181e41f4b71Sopenharmony_ci } else { 182e41f4b71Sopenharmony_ci // Destroy the NativeModule component. 183e41f4b71Sopenharmony_ci nativeNode.destroyNativeRoot() 184e41f4b71Sopenharmony_ci } 185e41f4b71Sopenharmony_ci } 186e41f4b71Sopenharmony_ci 187e41f4b71Sopenharmony_ci build() { 188e41f4b71Sopenharmony_ci Column() { 189e41f4b71Sopenharmony_ci Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => { 190e41f4b71Sopenharmony_ci this.showNative = !this.showNative 191e41f4b71Sopenharmony_ci }) 192e41f4b71Sopenharmony_ci Row() { 193e41f4b71Sopenharmony_ci // ArkTS inserts the native component. 194e41f4b71Sopenharmony_ci ContentSlot(this.rootSlot) 195e41f4b71Sopenharmony_ci }.layoutWeight(1) 196e41f4b71Sopenharmony_ci } 197e41f4b71Sopenharmony_ci .width('100%') 198e41f4b71Sopenharmony_ci .height('100%') 199e41f4b71Sopenharmony_ci } 200e41f4b71Sopenharmony_ci } 201e41f4b71Sopenharmony_ci ``` 202e41f4b71Sopenharmony_ci 203e41f4b71Sopenharmony_ci ```cpp 204e41f4b71Sopenharmony_ci // native_init.cpp 205e41f4b71Sopenharmony_ci #include "ArkUIMixedRefresh.h" 206e41f4b71Sopenharmony_ci #include "NativeEntry.h" 207e41f4b71Sopenharmony_ci #include "napi/native_api.h" 208e41f4b71Sopenharmony_ci 209e41f4b71Sopenharmony_ci EXTERN_C_START 210e41f4b71Sopenharmony_ci static napi_value Init(napi_env env, napi_value exports) { 211e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = { 212e41f4b71Sopenharmony_ci {"createNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr}, 213e41f4b71Sopenharmony_ci // Register the mixed mode creation function. 214e41f4b71Sopenharmony_ci {"registerCreateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterCreateRefresh, nullptr, 215e41f4b71Sopenharmony_ci nullptr, nullptr, napi_default, nullptr}, 216e41f4b71Sopenharmony_ci // Register the mixed mode update function. 217e41f4b71Sopenharmony_ci {"registerUpdateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterUpdateRefresh, nullptr, 218e41f4b71Sopenharmony_ci nullptr, nullptr, napi_default, nullptr}, 219e41f4b71Sopenharmony_ci {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default, 220e41f4b71Sopenharmony_ci nullptr}}; 221e41f4b71Sopenharmony_ci napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 222e41f4b71Sopenharmony_ci return exports; 223e41f4b71Sopenharmony_ci } 224e41f4b71Sopenharmony_ci EXTERN_C_END 225e41f4b71Sopenharmony_ci 226e41f4b71Sopenharmony_ci static napi_module demoModule = { 227e41f4b71Sopenharmony_ci .nm_version = 1, 228e41f4b71Sopenharmony_ci .nm_flags = 0, 229e41f4b71Sopenharmony_ci .nm_filename = nullptr, 230e41f4b71Sopenharmony_ci .nm_register_func = Init, 231e41f4b71Sopenharmony_ci .nm_modname = "entry", 232e41f4b71Sopenharmony_ci .nm_priv = ((void *)0), 233e41f4b71Sopenharmony_ci .reserved = {0}, 234e41f4b71Sopenharmony_ci }; 235e41f4b71Sopenharmony_ci 236e41f4b71Sopenharmony_ci extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } 237e41f4b71Sopenharmony_ci ``` 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci3. The native side saves the creation and update functions through the Node-API for subsequent calls. 240e41f4b71Sopenharmony_ci ```c 241e41f4b71Sopenharmony_ci // ArkUIMixedRefresh.h 242e41f4b71Sopenharmony_ci // Mixed mode interaction class. 243e41f4b71Sopenharmony_ci 244e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H 245e41f4b71Sopenharmony_ci #define MYAPPLICATION_ARKUIMIXEDREFRESH_H 246e41f4b71Sopenharmony_ci 247e41f4b71Sopenharmony_ci #include "ArkUIMixedNode.h" 248e41f4b71Sopenharmony_ci 249e41f4b71Sopenharmony_ci #include <optional> 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci #include <arkui/native_node_napi.h> 252e41f4b71Sopenharmony_ci #include <js_native_api_types.h> 253e41f4b71Sopenharmony_ci 254e41f4b71Sopenharmony_ci namespace NativeModule { 255e41f4b71Sopenharmony_ci 256e41f4b71Sopenharmony_ci class ArkUIMixedRefresh : public ArkUIMixedNode { 257e41f4b71Sopenharmony_ci public: 258e41f4b71Sopenharmony_ci static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info); 259e41f4b71Sopenharmony_ci static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info); 260e41f4b71Sopenharmony_ci }; 261e41f4b71Sopenharmony_ci 262e41f4b71Sopenharmony_ci } // namespace NativeModule 263e41f4b71Sopenharmony_ci 264e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H 265e41f4b71Sopenharmony_ci ``` 266e41f4b71Sopenharmony_ci 267e41f4b71Sopenharmony_ci ```cpp 268e41f4b71Sopenharmony_ci // ArkUIMixedRefresh.cpp 269e41f4b71Sopenharmony_ci // Mixed mode interaction class. 270e41f4b71Sopenharmony_ci 271e41f4b71Sopenharmony_ci #include "ArkUIMixedRefresh.h" 272e41f4b71Sopenharmony_ci #include <hilog/log.h> 273e41f4b71Sopenharmony_ci 274e41f4b71Sopenharmony_ci namespace NativeModule { 275e41f4b71Sopenharmony_ci namespace { 276e41f4b71Sopenharmony_ci napi_env g_env; 277e41f4b71Sopenharmony_ci napi_ref g_createRefresh; 278e41f4b71Sopenharmony_ci napi_ref g_updateRefresh; 279e41f4b71Sopenharmony_ci } // namespace 280e41f4b71Sopenharmony_ci 281e41f4b71Sopenharmony_ci napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) { 282e41f4b71Sopenharmony_ci size_t argc = 1; 283e41f4b71Sopenharmony_ci napi_value args[1] = {nullptr}; 284e41f4b71Sopenharmony_ci 285e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 286e41f4b71Sopenharmony_ci 287e41f4b71Sopenharmony_ci g_env = env; 288e41f4b71Sopenharmony_ci napi_ref refer; 289e41f4b71Sopenharmony_ci // Save the reference after creation to prevent it from being released. 290e41f4b71Sopenharmony_ci napi_create_reference(env, args[0], 1, &refer); 291e41f4b71Sopenharmony_ci 292e41f4b71Sopenharmony_ci g_createRefresh = refer; 293e41f4b71Sopenharmony_ci return nullptr; 294e41f4b71Sopenharmony_ci } 295e41f4b71Sopenharmony_ci 296e41f4b71Sopenharmony_ci napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) { 297e41f4b71Sopenharmony_ci size_t argc = 1; 298e41f4b71Sopenharmony_ci napi_value args[1] = {nullptr}; 299e41f4b71Sopenharmony_ci 300e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 301e41f4b71Sopenharmony_ci 302e41f4b71Sopenharmony_ci g_env = env; 303e41f4b71Sopenharmony_ci napi_ref refer; 304e41f4b71Sopenharmony_ci // Save the reference after creation to prevent it from being released. 305e41f4b71Sopenharmony_ci napi_create_reference(env, args[0], 1, &refer); 306e41f4b71Sopenharmony_ci 307e41f4b71Sopenharmony_ci g_updateRefresh = refer; 308e41f4b71Sopenharmony_ci return nullptr; 309e41f4b71Sopenharmony_ci } 310e41f4b71Sopenharmony_ci 311e41f4b71Sopenharmony_ci } // namespace NativeModule 312e41f4b71Sopenharmony_ci ``` 313e41f4b71Sopenharmony_ci 314e41f4b71Sopenharmony_ci4. Abstract the base class of components in mixed mode for general logic management. 315e41f4b71Sopenharmony_ci ```c 316e41f4b71Sopenharmony_ci // ArkUIMixedNode.h 317e41f4b71Sopenharmony_ci // Base class for mixed mode. 318e41f4b71Sopenharmony_ci 319e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_ARKUIMIXEDNODE_H 320e41f4b71Sopenharmony_ci #define MYAPPLICATION_ARKUIMIXEDNODE_H 321e41f4b71Sopenharmony_ci 322e41f4b71Sopenharmony_ci #include <js_native_api.h> 323e41f4b71Sopenharmony_ci #include <js_native_api_types.h> 324e41f4b71Sopenharmony_ci 325e41f4b71Sopenharmony_ci #include "ArkUIBaseNode.h" 326e41f4b71Sopenharmony_ci #include "NativeModule.h" 327e41f4b71Sopenharmony_ci 328e41f4b71Sopenharmony_ci namespace NativeModule { 329e41f4b71Sopenharmony_ci 330e41f4b71Sopenharmony_ci // Wrap ArkTS Node 331e41f4b71Sopenharmony_ci class ArkUIMixedNode : public ArkUIBaseNode { 332e41f4b71Sopenharmony_ci public: 333e41f4b71Sopenharmony_ci ArkUIMixedNode(ArkUI_NodeHandle handle, napi_env env, napi_ref componentContent) 334e41f4b71Sopenharmony_ci : ArkUIBaseNode(handle), env_(env), componentContent_(componentContent) {} 335e41f4b71Sopenharmony_ci 336e41f4b71Sopenharmony_ci // In the base class destructor, the object on the ArkTS side in mixed mode needs to be released. 337e41f4b71Sopenharmony_ci ~ArkUIMixedNode() override { napi_delete_reference(env_, componentContent_); } 338e41f4b71Sopenharmony_ci 339e41f4b71Sopenharmony_ci protected: 340e41f4b71Sopenharmony_ci napi_env env_; 341e41f4b71Sopenharmony_ci napi_ref componentContent_; 342e41f4b71Sopenharmony_ci }; 343e41f4b71Sopenharmony_ci 344e41f4b71Sopenharmony_ci } // namespace NativeModule 345e41f4b71Sopenharmony_ci 346e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_ARKUIMIXEDNODE_H 347e41f4b71Sopenharmony_ci ``` 348e41f4b71Sopenharmony_ci 349e41f4b71Sopenharmony_ci5. Implement the encapsulation object for the **Refresh** component in mixed mode. 350e41f4b71Sopenharmony_ci ```c 351e41f4b71Sopenharmony_ci // ArkUIMixedRefresh.h 352e41f4b71Sopenharmony_ci // The encapsulation object of Refresh in mixed mode on the native side. 353e41f4b71Sopenharmony_ci 354e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H 355e41f4b71Sopenharmony_ci #define MYAPPLICATION_ARKUIMIXEDREFRESH_H 356e41f4b71Sopenharmony_ci 357e41f4b71Sopenharmony_ci #include "ArkUIMixedNode.h" 358e41f4b71Sopenharmony_ci #include "ArkUIBaseNode.h" 359e41f4b71Sopenharmony_ci 360e41f4b71Sopenharmony_ci #include <optional> 361e41f4b71Sopenharmony_ci 362e41f4b71Sopenharmony_ci #include <arkui/native_node_napi.h> 363e41f4b71Sopenharmony_ci #include <js_native_api_types.h> 364e41f4b71Sopenharmony_ci 365e41f4b71Sopenharmony_ci namespace NativeModule { 366e41f4b71Sopenharmony_ci 367e41f4b71Sopenharmony_ci // Define the interaction data structure between the native side and the ArkTS side. 368e41f4b71Sopenharmony_ci struct NativeRefreshAttribute { 369e41f4b71Sopenharmony_ci std::optional<bool> isRefreshing; 370e41f4b71Sopenharmony_ci std::optional<float> width; 371e41f4b71Sopenharmony_ci std::optional<float> height; 372e41f4b71Sopenharmony_ci std::optional<uint32_t> backgroundColor; 373e41f4b71Sopenharmony_ci std::optional<float> refreshOffset; 374e41f4b71Sopenharmony_ci std::optional<bool> pullToRefresh; 375e41f4b71Sopenharmony_ci std::function<void()> onRefreshing; 376e41f4b71Sopenharmony_ci std::function<void(float)> onOffsetChange; 377e41f4b71Sopenharmony_ci }; 378e41f4b71Sopenharmony_ci 379e41f4b71Sopenharmony_ci class ArkUIMixedRefresh : public ArkUIMixedNode { 380e41f4b71Sopenharmony_ci public: 381e41f4b71Sopenharmony_ci // Call the ArkTS method to create the Refresh component. 382e41f4b71Sopenharmony_ci static const std::shared_ptr<ArkUIMixedRefresh> Create(const NativeRefreshAttribute &attribute); 383e41f4b71Sopenharmony_ci 384e41f4b71Sopenharmony_ci ArkUIMixedRefresh(ArkUI_NodeHandle handle, ArkUI_NodeContentHandle contentHandle, napi_env env, 385e41f4b71Sopenharmony_ci napi_ref componentContent, napi_ref nodeContent) 386e41f4b71Sopenharmony_ci : ArkUIMixedNode(handle, env, componentContent), contentHandle_(contentHandle), nodeContent_(nodeContent) {} 387e41f4b71Sopenharmony_ci 388e41f4b71Sopenharmony_ci ArkUIMixedRefresh() : ArkUIMixedNode(nullptr, nullptr, nullptr) {} 389e41f4b71Sopenharmony_ci 390e41f4b71Sopenharmony_ci ~ArkUIMixedRefresh() override { napi_delete_reference(env_, nodeContent_); } // Release the placeholder component slot object for the child node. 391e41f4b71Sopenharmony_ci 392e41f4b71Sopenharmony_ci void SetWidth(float width) { attribute_.width = width; } 393e41f4b71Sopenharmony_ci 394e41f4b71Sopenharmony_ci void SetHeight(float height) { attribute_.height = height; } 395e41f4b71Sopenharmony_ci 396e41f4b71Sopenharmony_ci void SetBackgroundColor(uint32_t color) { attribute_.backgroundColor = color; } 397e41f4b71Sopenharmony_ci 398e41f4b71Sopenharmony_ci void SetRefreshState(bool isRefreshing) { attribute_.isRefreshing = isRefreshing; } 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ci void SetPullToRefresh(bool pullToRefresh) { attribute_.pullToRefresh = pullToRefresh; } 401e41f4b71Sopenharmony_ci 402e41f4b71Sopenharmony_ci void SetRefreshOffset(float offset) { attribute_.refreshOffset = offset; } 403e41f4b71Sopenharmony_ci 404e41f4b71Sopenharmony_ci void SetRefreshCallback(const std::function<void()> &callback) { attribute_.onRefreshing = callback; } 405e41f4b71Sopenharmony_ci 406e41f4b71Sopenharmony_ci void SetOnOffsetChange(const std::function<void(float)> &callback) { attribute_.onOffsetChange = callback; } 407e41f4b71Sopenharmony_ci 408e41f4b71Sopenharmony_ci // To avoid frequent cross-language communication, cache property events on the native side and notify in batches. 409e41f4b71Sopenharmony_ci void FlushMixedModeCmd(); 410e41f4b71Sopenharmony_ci 411e41f4b71Sopenharmony_ci static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info); 412e41f4b71Sopenharmony_ci static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info); 413e41f4b71Sopenharmony_ci 414e41f4b71Sopenharmony_ci protected: 415e41f4b71Sopenharmony_ci void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override { 416e41f4b71Sopenharmony_ci assert(contentHandle_); 417e41f4b71Sopenharmony_ci // Use NodeContent to mount the component (can be a transformation object of ArkTS on the native side through ComponentContent, or a pure native component) under the ArkTS component. 418e41f4b71Sopenharmony_ci OH_ArkUI_NodeContent_AddNode(contentHandle_, child->GetHandle()); 419e41f4b71Sopenharmony_ci } 420e41f4b71Sopenharmony_ci 421e41f4b71Sopenharmony_ci void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override { 422e41f4b71Sopenharmony_ci assert(contentHandle_); 423e41f4b71Sopenharmony_ci // Use NodeContent to remove the component. 424e41f4b71Sopenharmony_ci OH_ArkUI_NodeContent_RemoveNode(contentHandle_, child->GetHandle()); 425e41f4b71Sopenharmony_ci } 426e41f4b71Sopenharmony_ci 427e41f4b71Sopenharmony_ci void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override { 428e41f4b71Sopenharmony_ci assert(contentHandle_); 429e41f4b71Sopenharmony_ci // Use NodeContent to insert the component. 430e41f4b71Sopenharmony_ci OH_ArkUI_NodeContent_InsertNode(contentHandle_, child->GetHandle(), index); 431e41f4b71Sopenharmony_ci } 432e41f4b71Sopenharmony_ci 433e41f4b71Sopenharmony_ci private: 434e41f4b71Sopenharmony_ci // Use the Node-API to create the data structure on the ArkTS side. 435e41f4b71Sopenharmony_ci static napi_value CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData); 436e41f4b71Sopenharmony_ci 437e41f4b71Sopenharmony_ci ArkUI_NodeContentHandle contentHandle_; 438e41f4b71Sopenharmony_ci napi_ref nodeContent_; 439e41f4b71Sopenharmony_ci NativeRefreshAttribute attribute_; 440e41f4b71Sopenharmony_ci }; 441e41f4b71Sopenharmony_ci 442e41f4b71Sopenharmony_ci } // namespace NativeModule 443e41f4b71Sopenharmony_ci 444e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H 445e41f4b71Sopenharmony_ci ``` 446e41f4b71Sopenharmony_ci 447e41f4b71Sopenharmony_ci Related implementation class description: 448e41f4b71Sopenharmony_ci 449e41f4b71Sopenharmony_ci ```c 450e41f4b71Sopenharmony_ci #include "ArkUIMixedRefresh.h" 451e41f4b71Sopenharmony_ci #include <hilog/log.h> 452e41f4b71Sopenharmony_ci 453e41f4b71Sopenharmony_ci namespace NativeModule { 454e41f4b71Sopenharmony_ci namespace { 455e41f4b71Sopenharmony_ci napi_env g_env; 456e41f4b71Sopenharmony_ci napi_ref g_createRefresh; 457e41f4b71Sopenharmony_ci napi_ref g_updateRefresh; 458e41f4b71Sopenharmony_ci } // namespace 459e41f4b71Sopenharmony_ci 460e41f4b71Sopenharmony_ci // Use the Node-API to create the data structure for interaction with the ArkTS side, used for the creation and update of the Refresh component. 461e41f4b71Sopenharmony_ci napi_value ArkUIMixedRefresh::CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData) { 462e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = { 463e41f4b71Sopenharmony_ci {"width", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 464e41f4b71Sopenharmony_ci {"height", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 465e41f4b71Sopenharmony_ci {"backgroundColor", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 466e41f4b71Sopenharmony_ci {"pullToRefresh", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 467e41f4b71Sopenharmony_ci {"isRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 468e41f4b71Sopenharmony_ci {"refreshOffset", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 469e41f4b71Sopenharmony_ci {"onRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 470e41f4b71Sopenharmony_ci {"onOffsetChange", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, 471e41f4b71Sopenharmony_ci }; 472e41f4b71Sopenharmony_ci if (attribute.width) { 473e41f4b71Sopenharmony_ci napi_value width; 474e41f4b71Sopenharmony_ci napi_create_double(g_env, attribute.width.value(), &width); 475e41f4b71Sopenharmony_ci desc[0].value = width; 476e41f4b71Sopenharmony_ci } 477e41f4b71Sopenharmony_ci if (attribute.height) { 478e41f4b71Sopenharmony_ci napi_value height; 479e41f4b71Sopenharmony_ci napi_create_double(g_env, attribute.height.value(), &height); 480e41f4b71Sopenharmony_ci desc[1].value = height; 481e41f4b71Sopenharmony_ci } 482e41f4b71Sopenharmony_ci if (attribute.backgroundColor) { 483e41f4b71Sopenharmony_ci napi_value backgroundColor; 484e41f4b71Sopenharmony_ci napi_create_uint32(g_env, attribute.backgroundColor.value(), &backgroundColor); 485e41f4b71Sopenharmony_ci desc[2].value = backgroundColor; 486e41f4b71Sopenharmony_ci } 487e41f4b71Sopenharmony_ci if (attribute.pullToRefresh) { 488e41f4b71Sopenharmony_ci napi_value pullToRefresh; 489e41f4b71Sopenharmony_ci napi_create_int32(g_env, attribute.pullToRefresh.value(), &pullToRefresh); 490e41f4b71Sopenharmony_ci desc[3].value = pullToRefresh; 491e41f4b71Sopenharmony_ci } 492e41f4b71Sopenharmony_ci if (attribute.isRefreshing) { 493e41f4b71Sopenharmony_ci napi_value isRefreshing; 494e41f4b71Sopenharmony_ci napi_create_int32(g_env, attribute.isRefreshing.value(), &isRefreshing); 495e41f4b71Sopenharmony_ci desc[4].value = isRefreshing; 496e41f4b71Sopenharmony_ci } 497e41f4b71Sopenharmony_ci if (attribute.refreshOffset) { 498e41f4b71Sopenharmony_ci napi_value refreshOffset; 499e41f4b71Sopenharmony_ci napi_create_double(g_env, attribute.refreshOffset.value(), &refreshOffset); 500e41f4b71Sopenharmony_ci desc[5].value = refreshOffset; 501e41f4b71Sopenharmony_ci } 502e41f4b71Sopenharmony_ci if (attribute.onRefreshing) { 503e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "onRefreshing start"); 504e41f4b71Sopenharmony_ci desc[6].method = [](napi_env env, napi_callback_info info) -> napi_value { 505e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "onRefreshing callback"); 506e41f4b71Sopenharmony_ci size_t argc = 0; 507e41f4b71Sopenharmony_ci napi_value args[0]; 508e41f4b71Sopenharmony_ci void *data; 509e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, &data); 510e41f4b71Sopenharmony_ci auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(data); 511e41f4b71Sopenharmony_ci if (refresh && refresh->attribute_.onRefreshing) { 512e41f4b71Sopenharmony_ci refresh->attribute_.onRefreshing(); 513e41f4b71Sopenharmony_ci } 514e41f4b71Sopenharmony_ci return nullptr; 515e41f4b71Sopenharmony_ci }; 516e41f4b71Sopenharmony_ci } 517e41f4b71Sopenharmony_ci if (attribute.onOffsetChange) { 518e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "onOffsetChange start"); 519e41f4b71Sopenharmony_ci desc[7].method = [](napi_env env, napi_callback_info info) -> napi_value { 520e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "onOffsetChange callback"); 521e41f4b71Sopenharmony_ci size_t argc = 1; 522e41f4b71Sopenharmony_ci napi_value args[1] = {nullptr}; 523e41f4b71Sopenharmony_ci void *data; 524e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, &data); 525e41f4b71Sopenharmony_ci double offset = 0.0; 526e41f4b71Sopenharmony_ci napi_get_value_double(env, args[0], &offset); 527e41f4b71Sopenharmony_ci auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(data); 528e41f4b71Sopenharmony_ci if (refresh && refresh->attribute_.onOffsetChange) { 529e41f4b71Sopenharmony_ci refresh->attribute_.onOffsetChange(offset); 530e41f4b71Sopenharmony_ci } 531e41f4b71Sopenharmony_ci return nullptr; 532e41f4b71Sopenharmony_ci }; 533e41f4b71Sopenharmony_ci } 534e41f4b71Sopenharmony_ci napi_value refreshAttribute = nullptr; 535e41f4b71Sopenharmony_ci auto result = napi_create_object_with_properties(g_env, &refreshAttribute, sizeof(desc) / sizeof(desc[0]), desc); 536e41f4b71Sopenharmony_ci if (result != napi_ok) { 537e41f4b71Sopenharmony_ci return nullptr; 538e41f4b71Sopenharmony_ci } 539e41f4b71Sopenharmony_ci return refreshAttribute; 540e41f4b71Sopenharmony_ci } 541e41f4b71Sopenharmony_ci 542e41f4b71Sopenharmony_ci // Create the component on the ArkTS side and save it in the encapsulation object on the native side. 543e41f4b71Sopenharmony_ci const std::shared_ptr<ArkUIMixedRefresh> ArkUIMixedRefresh::Create(const NativeRefreshAttribute &attribute) { 544e41f4b71Sopenharmony_ci napi_handle_scope scope; 545e41f4b71Sopenharmony_ci napi_open_handle_scope(g_env, &scope); 546e41f4b71Sopenharmony_ci auto refresh = std::make_shared<ArkUIMixedRefresh>(); 547e41f4b71Sopenharmony_ci auto refreshAttribute = CreateRefreshAttribute(attribute, refresh.get()); 548e41f4b71Sopenharmony_ci if (refreshAttribute == nullptr) { 549e41f4b71Sopenharmony_ci napi_close_handle_scope(g_env, scope); 550e41f4b71Sopenharmony_ci return nullptr; 551e41f4b71Sopenharmony_ci } 552e41f4b71Sopenharmony_ci napi_value result = nullptr; 553e41f4b71Sopenharmony_ci napi_value argv[1] = {refreshAttribute}; 554e41f4b71Sopenharmony_ci napi_value createRefresh = nullptr; 555e41f4b71Sopenharmony_ci napi_get_reference_value(g_env, g_createRefresh, &createRefresh); 556e41f4b71Sopenharmony_ci // Call the ArkTS Create function to create the ArkTS ComponentContent. 557e41f4b71Sopenharmony_ci napi_call_function(g_env, nullptr, createRefresh, 1, argv, &result); 558e41f4b71Sopenharmony_ci 559e41f4b71Sopenharmony_ci // Obtain the ArkTS Refresh component. 560e41f4b71Sopenharmony_ci napi_value componentContent = nullptr; 561e41f4b71Sopenharmony_ci napi_get_named_property(g_env, result, "content", &componentContent); 562e41f4b71Sopenharmony_ci ArkUI_NodeHandle handle; 563e41f4b71Sopenharmony_ci OH_ArkUI_GetNodeHandleFromNapiValue(g_env, componentContent, &handle); 564e41f4b71Sopenharmony_ci assert(handle); 565e41f4b71Sopenharmony_ci // Obtain the child component slot of the ArkTS Refresh component. 566e41f4b71Sopenharmony_ci napi_value nodeContent = nullptr; 567e41f4b71Sopenharmony_ci napi_get_named_property(g_env, result, "childSlot", &nodeContent); 568e41f4b71Sopenharmony_ci ArkUI_NodeContentHandle contentHandle; 569e41f4b71Sopenharmony_ci OH_ArkUI_GetNodeContentFromNapiValue(g_env, nodeContent, &contentHandle); 570e41f4b71Sopenharmony_ci assert(contentHandle); 571e41f4b71Sopenharmony_ci // Save the ArkTS ComponentContent to prevent the object on the ArkTS side from being released and for subsequent updates. 572e41f4b71Sopenharmony_ci napi_ref componentContentRef; 573e41f4b71Sopenharmony_ci napi_create_reference(g_env, componentContent, 1, &componentContentRef); 574e41f4b71Sopenharmony_ci // Save the ArkTS NodeContent to prevent the object on the ArkTS side from being released and for subsequent updates. 575e41f4b71Sopenharmony_ci napi_ref nodeContentRef; 576e41f4b71Sopenharmony_ci napi_create_reference(g_env, nodeContent, 1, &nodeContentRef); 577e41f4b71Sopenharmony_ci // Update the Refresh component related parameters. 578e41f4b71Sopenharmony_ci refresh->handle_ = handle; 579e41f4b71Sopenharmony_ci refresh->env_ = g_env; 580e41f4b71Sopenharmony_ci refresh->componentContent_ = componentContentRef; 581e41f4b71Sopenharmony_ci refresh->nodeContent_ = nodeContentRef; 582e41f4b71Sopenharmony_ci refresh->contentHandle_ = contentHandle; 583e41f4b71Sopenharmony_ci refresh->attribute_ = attribute; 584e41f4b71Sopenharmony_ci return refresh; 585e41f4b71Sopenharmony_ci } 586e41f4b71Sopenharmony_ci // Implementation of the update function. 587e41f4b71Sopenharmony_ci void ArkUIMixedRefresh::FlushMixedModeCmd() { 588e41f4b71Sopenharmony_ci napi_handle_scope scope; 589e41f4b71Sopenharmony_ci napi_open_handle_scope(g_env, &scope); 590e41f4b71Sopenharmony_ci // Create the input parameters for the call to the ArkTS API. 591e41f4b71Sopenharmony_ci auto refreshAttribute = CreateRefreshAttribute(attribute_, this); 592e41f4b71Sopenharmony_ci if (refreshAttribute == nullptr) { 593e41f4b71Sopenharmony_ci napi_close_handle_scope(g_env, scope); 594e41f4b71Sopenharmony_ci return; 595e41f4b71Sopenharmony_ci } 596e41f4b71Sopenharmony_ci // Obtain the remaining two API parameters for the update API. 597e41f4b71Sopenharmony_ci napi_value componentContent = nullptr; 598e41f4b71Sopenharmony_ci napi_get_reference_value(g_env, componentContent_, &componentContent); 599e41f4b71Sopenharmony_ci napi_value nodeContent = nullptr; 600e41f4b71Sopenharmony_ci napi_get_reference_value(g_env, nodeContent_, &nodeContent); 601e41f4b71Sopenharmony_ci 602e41f4b71Sopenharmony_ci napi_value argv[3] = {componentContent, nodeContent, refreshAttribute}; 603e41f4b71Sopenharmony_ci napi_value updateRefresh = nullptr; 604e41f4b71Sopenharmony_ci napi_get_reference_value(g_env, g_updateRefresh, &updateRefresh); 605e41f4b71Sopenharmony_ci // Call the ArkTS Update function to update. 606e41f4b71Sopenharmony_ci napi_value result = nullptr; 607e41f4b71Sopenharmony_ci napi_call_function(g_env, nullptr, updateRefresh, 3, argv, &result); 608e41f4b71Sopenharmony_ci } 609e41f4b71Sopenharmony_ci 610e41f4b71Sopenharmony_ci napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) { 611e41f4b71Sopenharmony_ci size_t argc = 1; 612e41f4b71Sopenharmony_ci napi_value args[1] = {nullptr}; 613e41f4b71Sopenharmony_ci 614e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 615e41f4b71Sopenharmony_ci 616e41f4b71Sopenharmony_ci g_env = env; 617e41f4b71Sopenharmony_ci napi_ref refer; 618e41f4b71Sopenharmony_ci napi_create_reference(env, args[0], 1, &refer); 619e41f4b71Sopenharmony_ci 620e41f4b71Sopenharmony_ci g_createRefresh = refer; 621e41f4b71Sopenharmony_ci return nullptr; 622e41f4b71Sopenharmony_ci } 623e41f4b71Sopenharmony_ci 624e41f4b71Sopenharmony_ci napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) { 625e41f4b71Sopenharmony_ci size_t argc = 1; 626e41f4b71Sopenharmony_ci napi_value args[1] = {nullptr}; 627e41f4b71Sopenharmony_ci 628e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 629e41f4b71Sopenharmony_ci 630e41f4b71Sopenharmony_ci g_env = env; 631e41f4b71Sopenharmony_ci napi_ref refer; 632e41f4b71Sopenharmony_ci napi_create_reference(env, args[0], 1, &refer); 633e41f4b71Sopenharmony_ci 634e41f4b71Sopenharmony_ci g_updateRefresh = refer; 635e41f4b71Sopenharmony_ci return nullptr; 636e41f4b71Sopenharmony_ci } 637e41f4b71Sopenharmony_ci 638e41f4b71Sopenharmony_ci } // namespace NativeModule 639e41f4b71Sopenharmony_ci 640e41f4b71Sopenharmony_ci ``` 641e41f4b71Sopenharmony_ci 642e41f4b71Sopenharmony_ci6. Use the page structure from the [Integrating with ArkTS Page](ndk-access-the-arkts-page.md) section, and continue with the [timer module simple implementation](ndk-loading-long-list.md), making the **Refresh** component the parent component of the text list. 643e41f4b71Sopenharmony_ci ```c 644e41f4b71Sopenharmony_ci // MixedRefreshExample.h 645e41f4b71Sopenharmony_ci // Sample code for mixed mode. 646e41f4b71Sopenharmony_ci 647e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_MIXEDREFRESHEXAMPLE_H 648e41f4b71Sopenharmony_ci #define MYAPPLICATION_MIXEDREFRESHEXAMPLE_H 649e41f4b71Sopenharmony_ci 650e41f4b71Sopenharmony_ci #include "ArkUIBaseNode.h" 651e41f4b71Sopenharmony_ci #include "ArkUIMixedRefresh.h" 652e41f4b71Sopenharmony_ci #include "TextListExample.h" 653e41f4b71Sopenharmony_ci #include "UITimer.h" 654e41f4b71Sopenharmony_ci 655e41f4b71Sopenharmony_ci #include <js_native_api_types.h> 656e41f4b71Sopenharmony_ci 657e41f4b71Sopenharmony_ci namespace NativeModule { 658e41f4b71Sopenharmony_ci 659e41f4b71Sopenharmony_ci std::shared_ptr<ArkUIBaseNode> CreateMixedRefreshList(napi_env env) { 660e41f4b71Sopenharmony_ci auto list = CreateTextListExample(); 661e41f4b71Sopenharmony_ci // Create the Refresh component in mixed mode and mount the List component. 662e41f4b71Sopenharmony_ci NativeRefreshAttribute nativeRefreshAttribute{ 663e41f4b71Sopenharmony_ci .backgroundColor = 0xFF89CFF0, .refreshOffset = 64, .pullToRefresh = true}; 664e41f4b71Sopenharmony_ci auto refresh = ArkUIMixedRefresh::Create(nativeRefreshAttribute); 665e41f4b71Sopenharmony_ci refresh->AddChild(list); 666e41f4b71Sopenharmony_ci 667e41f4b71Sopenharmony_ci // Set the event for mixed mode. 668e41f4b71Sopenharmony_ci refresh->SetOnOffsetChange( 669e41f4b71Sopenharmony_ci [](float offset) { OH_LOG_INFO(LOG_APP, "on refresh offset changed: %{public}f", offset); }); 670e41f4b71Sopenharmony_ci refresh->SetRefreshCallback([refreshPtr = refresh.get(), env]() { 671e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "on refreshing"); 672e41f4b71Sopenharmony_ci // Start the timer to simulate data acquisition. 673e41f4b71Sopenharmony_ci CreateNativeTimer(env, refreshPtr, 1, [](void *userData, int32_t count) { 674e41f4b71Sopenharmony_ci // Disable the refresh feature after data is obtained. 675e41f4b71Sopenharmony_ci auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(userData); 676e41f4b71Sopenharmony_ci refresh->SetRefreshState(false); 677e41f4b71Sopenharmony_ci refresh->FlushMixedModeCmd(); 678e41f4b71Sopenharmony_ci }); 679e41f4b71Sopenharmony_ci }); 680e41f4b71Sopenharmony_ci 681e41f4b71Sopenharmony_ci // Update the event to the ArkTS side. 682e41f4b71Sopenharmony_ci refresh->FlushMixedModeCmd(); 683e41f4b71Sopenharmony_ci return refresh; 684e41f4b71Sopenharmony_ci } 685e41f4b71Sopenharmony_ci 686e41f4b71Sopenharmony_ci } // namespace NativeModule 687e41f4b71Sopenharmony_ci 688e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_MIXEDREFRESHEXAMPLE_H 689e41f4b71Sopenharmony_ci ``` 690e41f4b71Sopenharmony_ci 691e41f4b71Sopenharmony_ci Replace the entry component creation with the pull-to-refresh text list. 692e41f4b71Sopenharmony_ci 693e41f4b71Sopenharmony_ci ```c 694e41f4b71Sopenharmony_ci #include "NativeEntry.h" 695e41f4b71Sopenharmony_ci 696e41f4b71Sopenharmony_ci #include "ArkUIMixedRefresh.h" 697e41f4b71Sopenharmony_ci #include "MixedRefreshExample.h" 698e41f4b71Sopenharmony_ci #include "TextListExample.h" 699e41f4b71Sopenharmony_ci 700e41f4b71Sopenharmony_ci #include <arkui/native_node_napi.h> 701e41f4b71Sopenharmony_ci #include <arkui/native_type.h> 702e41f4b71Sopenharmony_ci #include <js_native_api.h> 703e41f4b71Sopenharmony_ci #include <uv.h> 704e41f4b71Sopenharmony_ci 705e41f4b71Sopenharmony_ci namespace NativeModule { 706e41f4b71Sopenharmony_ci 707e41f4b71Sopenharmony_ci napi_value CreateNativeRoot(napi_env env, napi_callback_info info) { 708e41f4b71Sopenharmony_ci size_t argc = 1; 709e41f4b71Sopenharmony_ci napi_value args[1] = {nullptr}; 710e41f4b71Sopenharmony_ci 711e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 712e41f4b71Sopenharmony_ci 713e41f4b71Sopenharmony_ci // Obtain NodeContent. 714e41f4b71Sopenharmony_ci ArkUI_NodeContentHandle contentHandle; 715e41f4b71Sopenharmony_ci OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); 716e41f4b71Sopenharmony_ci NativeEntry::GetInstance()->SetContentHandle(contentHandle); 717e41f4b71Sopenharmony_ci 718e41f4b71Sopenharmony_ci // Create a Refresh text list. 719e41f4b71Sopenharmony_ci auto refresh = CreateMixedRefreshList(env); 720e41f4b71Sopenharmony_ci 721e41f4b71Sopenharmony_ci // Keep the native side object in the management class to maintain its lifecycle. 722e41f4b71Sopenharmony_ci NativeEntry::GetInstance()->SetRootNode(refresh); 723e41f4b71Sopenharmony_ci return nullptr; 724e41f4b71Sopenharmony_ci } 725e41f4b71Sopenharmony_ci 726e41f4b71Sopenharmony_ci napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) { 727e41f4b71Sopenharmony_ci // Release the native side object from the management class. 728e41f4b71Sopenharmony_ci NativeEntry::GetInstance()->DisposeRootNode(); 729e41f4b71Sopenharmony_ci return nullptr; 730e41f4b71Sopenharmony_ci } 731e41f4b71Sopenharmony_ci 732e41f4b71Sopenharmony_ci } // namespace NativeModule 733e41f4b71Sopenharmony_ci 734e41f4b71Sopenharmony_ci ``` 735