# Embedding ArkTS Components ArkUI on the native side offers a subset of ArkTS features, which excludes certain capabilities such as declarative UI syntax, custom struct components, and some advanced UI components. For 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. > **NOTE** > > - **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. > > - 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**. > > - 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. The following example introduces the ArkTS **Refresh** component based on the [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md) section. **Figure 1** Mounting a text list to a Refresh component  1. Register the ArkTS component creation function to the native side for it to call, and use the **ComponentContent** capability to encapsulate the creation function. ```ts // MixedModule.ets // Create ArkTS components using the ComponentContent capability. import { NodeContent, UIContext, RefreshModifier, ComponentContent } from '@kit.ArkUI'; // Define the data object for interaction between the native side and ArkTS. interface NativeRefreshAttribute { isRefreshing: boolean; width?: number; height?: number; backgroundColor?: number; refreshOffset?: number; pullToRefresh?: boolean onRefreshing?: () => void; onOffsetChange?: (offset: number) => void; } // Define the format of the input parameters for the @Builder function. interface RefreshAttribute { isRefreshing: boolean; // Optimize attribute settings for performance with Modifier. modifier?: RefreshModifier; slot?: NodeContent; onRefreshing?: () => void; onOffsetChange?: (offset: number) => void; } // ComponentContent encapsulates the ArkTS component dependency on the global @Builder function. You can nest @Component decorated custom components within the @Builder function when needed. // The @Builder function provides a way of passing parameters, making it convenient to update parameters later through the update API of ComponentContent. @Builder function mixedRefresh(attribute: RefreshAttribute) { Refresh({ refreshing: attribute.isRefreshing }) { // As a container component, Refresh needs to use the ContentSlot mechanism to reserve a place for child components. ContentSlot(attribute.slot) }.attributeModifier(attribute.modifier) .onRefreshing(() => { console.info("on onRefreshing"); if (attribute.onRefreshing) { console.info("on native onRefreshing"); attribute.onRefreshing(); } }) .onOffsetChange((value: number) => { console.info("on offset change: " + value); if (attribute.onOffsetChange) { console.info("on native onOffsetChange"); attribute.onOffsetChange(value); } }) } // Define the return value of the creation function for interaction between the ArkTS side and the native side. interface MixedModuleResult { // Define the encapsulated object for the Refresh construction function, used by the native side to convert to an ArkUI_NodeHandle object. content?: ComponentContent<RefreshAttribute>; // As a container component, Refresh needs to use the ContentSlot mechanism to mount child components from the native side. childSlot?: NodeContent; } // Provide an entry function for creating ArkTS components. export function createMixedRefresh(value: NativeRefreshAttribute): MixedModuleResult { console.info("createMixedRefresh"); // Use the AppStorage object to maintain the UI context object when the ability starts. let uiContent = AppStorage.get<UIContext>("context"); let modifier = new RefreshModifier(); if (value.width) { modifier.width(value.width) } if (value.height) { modifier.height(value.height) } if (value.backgroundColor) { modifier.backgroundColor(value.backgroundColor) } if (value.pullToRefresh) { modifier.pullToRefresh(value.pullToRefresh) } if (value.refreshOffset) { modifier.refreshOffset(value.refreshOffset) } // Create a NodeContent slot object for mounting Refresh child components. let nodeSlot = new NodeContent(); // Create the Refresh component using ComponentContent and encapsulate it. let content = new ComponentContent<RefreshAttribute>(uiContent!, wrapBuilder<[RefreshAttribute]>(mixedRefresh), { isRefreshing: value.isRefreshing, modifier: modifier, slot: nodeSlot, onRefreshing: value.onRefreshing, onOffsetChange: value.onOffsetChange }); // Pass the encapsulated object of the Refresh component and its child component slot object to the native side. return { content: content, childSlot: nodeSlot }; } // Define the update function for the Refresh component for updating by the native side. // 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. export function updateMixedRefresh(refresh: ComponentContent<RefreshAttribute>, childSlot: NodeContent, value: NativeRefreshAttribute): void { let modifier = new RefreshModifier(); if (value.width) { modifier.width(value.width) } if (value.height) { modifier.height(value.height) } if (value.backgroundColor) { modifier.backgroundColor(value.backgroundColor) } if (value.pullToRefresh) { modifier.pullToRefresh(value.pullToRefresh) } if (value.refreshOffset) { modifier.refreshOffset(value.refreshOffset) } // Call the update API of ComponentContent to update. refresh.update({ isRefreshing: value.isRefreshing, modifier: modifier, slot: childSlot, onRefreshing: value.onRefreshing, onOffsetChange: value.onOffsetChange }) } ``` 2. Register the creation and update functions with the native side. ```ts // entry.ets import nativeNode from 'libentry.so'; import { NodeContent } from '@kit.ArkUI'; import { createMixedRefresh, updateMixedRefresh } from './MixedModule' @Entry @Component struct Index { private rootSlot = new NodeContent(); @State @Watch('changeNativeFlag') showNative: boolean = false; aboutToAppear(): void { // Set the UI context. AppStorage.setOrCreate<UIContext>("context", this.getUIContext()); // Set the builder function for mixed mode. nativeNode.registerCreateMixedRefreshNode(createMixedRefresh); nativeNode.registerUpdateMixedRefreshNode(updateMixedRefresh); } changeNativeFlag(): void { if (this.showNative) { // Create and mount the NativeModule component. nativeNode.createNativeRoot(this.rootSlot) } else { // Destroy the NativeModule component. nativeNode.destroyNativeRoot() } } build() { Column() { Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => { this.showNative = !this.showNative }) Row() { // ArkTS inserts the native component. ContentSlot(this.rootSlot) }.layoutWeight(1) } .width('100%') .height('100%') } } ``` ```cpp // native_init.cpp #include "napi/native_api.h" #include "ArkUIMixedRefresh.h" #include "NativeEntry.h" EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { {"createNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr}, // Register the mixed mode creation function. {"registerCreateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterCreateRefresh, nullptr, nullptr, nullptr, napi_default, nullptr}, // Register the mixed mode update function. {"registerUpdateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterUpdateRefresh, nullptr, nullptr, nullptr, napi_default, nullptr}, {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr}}; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); return exports; } EXTERN_C_END static napi_module demoModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "entry", .nm_priv = ((void *)0), .reserved = {0}, }; extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } ``` 3. The native side saves the creation and update functions through the Node-API for subsequent calls. ```c // ArkUIMixedRefresh.h // Mixed mode interaction class. #ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H #define MYAPPLICATION_ARKUIMIXEDREFRESH_H #include "ArkUIMixedNode.h" #include <optional> #include <arkui/native_node_napi.h> #include <js_native_api_types.h> namespace NativeModule { class ArkUIMixedRefresh : public ArkUIMixedNode { public: static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info); static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info); }; } // namespace NativeModule #endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H ``` ```cpp // ArkUIMixedRefresh.cpp // Mixed mode interaction class. #include "ArkUIMixedRefresh.h" #include <hilog/log.h> namespace NativeModule { namespace { napi_env g_env; napi_ref g_createRefresh; napi_ref g_updateRefresh; } // namespace napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); g_env = env; napi_ref refer; // Save the reference after creation to prevent it from being released. napi_create_reference(env, args[0], 1, &refer); g_createRefresh = refer; return nullptr; } napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); g_env = env; napi_ref refer; // Save the reference after creation to prevent it from being released. napi_create_reference(env, args[0], 1, &refer); g_updateRefresh = refer; return nullptr; } } // namespace NativeModule ``` 4. Abstract the base class of components in mixed mode for general logic management. ```c // ArkUIMixedNode.h // Base class for mixed mode. #ifndef MYAPPLICATION_ARKUIMIXEDNODE_H #define MYAPPLICATION_ARKUIMIXEDNODE_H #include <js_native_api.h> #include <js_native_api_types.h> #include "ArkUIBaseNode.h" #include "NativeModule.h" namespace NativeModule { // Wrap ArkTS Node class ArkUIMixedNode : public ArkUIBaseNode { public: ArkUIMixedNode(ArkUI_NodeHandle handle, napi_env env, napi_ref componentContent) : ArkUIBaseNode(handle), env_(env), componentContent_(componentContent) {} // In the base class destructor, the object on the ArkTS side in mixed mode needs to be released. ~ArkUIMixedNode() override { napi_delete_reference(env_, componentContent_); } protected: napi_env env_; napi_ref componentContent_; }; } // namespace NativeModule #endif // MYAPPLICATION_ARKUIMIXEDNODE_H ``` 5. Implement the encapsulation object for the **Refresh** component in mixed mode. ```c // ArkUIMixedRefresh.h // The encapsulation object of Refresh in mixed mode on the native side. #ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H #define MYAPPLICATION_ARKUIMIXEDREFRESH_H #include "ArkUIMixedNode.h" #include "ArkUIBaseNode.h" #include <optional> #include <arkui/native_node_napi.h> #include <js_native_api_types.h> namespace NativeModule { // Define the interaction data structure between the native side and the ArkTS side. struct NativeRefreshAttribute { std::optional<bool> isRefreshing; std::optional<float> width; std::optional<float> height; std::optional<uint32_t> backgroundColor; std::optional<float> refreshOffset; std::optional<bool> pullToRefresh; std::function<void()> onRefreshing; std::function<void(float)> onOffsetChange; }; class ArkUIMixedRefresh : public ArkUIMixedNode { public: // Call the ArkTS method to create the Refresh component. static const std::shared_ptr<ArkUIMixedRefresh> Create(const NativeRefreshAttribute &attribute); ArkUIMixedRefresh(ArkUI_NodeHandle handle, ArkUI_NodeContentHandle contentHandle, napi_env env, napi_ref componentContent, napi_ref nodeContent) : ArkUIMixedNode(handle, env, componentContent), contentHandle_(contentHandle), nodeContent_(nodeContent) {} ArkUIMixedRefresh() : ArkUIMixedNode(nullptr, nullptr, nullptr) {} ~ArkUIMixedRefresh() override { napi_delete_reference(env_, nodeContent_); } // Release the placeholder component slot object for the child node. void SetWidth(float width) { attribute_.width = width; } void SetHeight(float height) { attribute_.height = height; } void SetBackgroundColor(uint32_t color) { attribute_.backgroundColor = color; } void SetRefreshState(bool isRefreshing) { attribute_.isRefreshing = isRefreshing; } void SetPullToRefresh(bool pullToRefresh) { attribute_.pullToRefresh = pullToRefresh; } void SetRefreshOffset(float offset) { attribute_.refreshOffset = offset; } void SetRefreshCallback(const std::function<void()> &callback) { attribute_.onRefreshing = callback; } void SetOnOffsetChange(const std::function<void(float)> &callback) { attribute_.onOffsetChange = callback; } // To avoid frequent cross-language communication, cache property events on the native side and notify in batches. void FlushMixedModeCmd(); static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info); static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info); protected: void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override { assert(contentHandle_); // 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. OH_ArkUI_NodeContent_AddNode(contentHandle_, child->GetHandle()); } void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override { assert(contentHandle_); // Use NodeContent to remove the component. OH_ArkUI_NodeContent_RemoveNode(contentHandle_, child->GetHandle()); } void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override { assert(contentHandle_); // Use NodeContent to insert the component. OH_ArkUI_NodeContent_InsertNode(contentHandle_, child->GetHandle(), index); } private: // Use the Node-API to create the data structure on the ArkTS side. static napi_value CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData); ArkUI_NodeContentHandle contentHandle_; napi_ref nodeContent_; NativeRefreshAttribute attribute_; }; } // namespace NativeModule #endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H ``` Related implementation class description: ```c #include "ArkUIMixedRefresh.h" #include <hilog/log.h> namespace NativeModule { namespace { napi_env g_env; napi_ref g_createRefresh; napi_ref g_updateRefresh; } // namespace // 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. napi_value ArkUIMixedRefresh::CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData) { napi_property_descriptor desc[] = { {"width", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, {"height", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, {"backgroundColor", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, {"pullToRefresh", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, {"isRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, {"refreshOffset", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, {"onRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, {"onOffsetChange", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData}, }; if (attribute.width) { napi_value width; napi_create_double(g_env, attribute.width.value(), &width); desc[0].value = width; } if (attribute.height) { napi_value height; napi_create_double(g_env, attribute.height.value(), &height); desc[1].value = height; } if (attribute.backgroundColor) { napi_value backgroundColor; napi_create_uint32(g_env, attribute.backgroundColor.value(), &backgroundColor); desc[2].value = backgroundColor; } if (attribute.pullToRefresh) { napi_value pullToRefresh; napi_create_int32(g_env, attribute.pullToRefresh.value(), &pullToRefresh); desc[3].value = pullToRefresh; } if (attribute.isRefreshing) { napi_value isRefreshing; napi_create_int32(g_env, attribute.isRefreshing.value(), &isRefreshing); desc[4].value = isRefreshing; } if (attribute.refreshOffset) { napi_value refreshOffset; napi_create_double(g_env, attribute.refreshOffset.value(), &refreshOffset); desc[5].value = refreshOffset; } if (attribute.onRefreshing) { OH_LOG_INFO(LOG_APP, "onRefreshing start"); desc[6].method = [](napi_env env, napi_callback_info info) -> napi_value { OH_LOG_INFO(LOG_APP, "onRefreshing callback"); size_t argc = 0; napi_value args[0]; void *data; napi_get_cb_info(env, info, &argc, args, nullptr, &data); auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(data); if (refresh && refresh->attribute_.onRefreshing) { refresh->attribute_.onRefreshing(); } return nullptr; }; } if (attribute.onOffsetChange) { OH_LOG_INFO(LOG_APP, "onOffsetChange start"); desc[7].method = [](napi_env env, napi_callback_info info) -> napi_value { OH_LOG_INFO(LOG_APP, "onOffsetChange callback"); size_t argc = 1; napi_value args[1] = {nullptr}; void *data; napi_get_cb_info(env, info, &argc, args, nullptr, &data); double offset = 0.0; napi_get_value_double(env, args[0], &offset); auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(data); if (refresh && refresh->attribute_.onOffsetChange) { refresh->attribute_.onOffsetChange(offset); } return nullptr; }; } napi_value refreshAttribute = nullptr; auto result = napi_create_object_with_properties(g_env, &refreshAttribute, sizeof(desc) / sizeof(desc[0]), desc); if (result != napi_ok) { return nullptr; } return refreshAttribute; } // Create the component on the ArkTS side and save it in the encapsulation object on the native side. const std::shared_ptr<ArkUIMixedRefresh> ArkUIMixedRefresh::Create(const NativeRefreshAttribute &attribute) { napi_handle_scope scope; napi_open_handle_scope(g_env, &scope); auto refresh = std::make_shared<ArkUIMixedRefresh>(); auto refreshAttribute = CreateRefreshAttribute(attribute, refresh.get()); if (refreshAttribute == nullptr) { napi_close_handle_scope(g_env, scope); return nullptr; } napi_value result = nullptr; napi_value argv[1] = {refreshAttribute}; napi_value createRefresh = nullptr; napi_get_reference_value(g_env, g_createRefresh, &createRefresh); // Call the ArkTS Create function to create the ArkTS ComponentContent. napi_call_function(g_env, nullptr, createRefresh, 1, argv, &result); // Obtain the ArkTS Refresh component. napi_value componentContent = nullptr; napi_get_named_property(g_env, result, "content", &componentContent); ArkUI_NodeHandle handle; OH_ArkUI_GetNodeHandleFromNapiValue(g_env, componentContent, &handle); assert(handle); // Obtain the child component slot of the ArkTS Refresh component. napi_value nodeContent = nullptr; napi_get_named_property(g_env, result, "childSlot", &nodeContent); ArkUI_NodeContentHandle contentHandle; OH_ArkUI_GetNodeContentFromNapiValue(g_env, nodeContent, &contentHandle); assert(contentHandle); // Save the ArkTS ComponentContent to prevent the object on the ArkTS side from being released and for subsequent updates. napi_ref componentContentRef; napi_create_reference(g_env, componentContent, 1, &componentContentRef); // Save the ArkTS NodeContent to prevent the object on the ArkTS side from being released and for subsequent updates. napi_ref nodeContentRef; napi_create_reference(g_env, nodeContent, 1, &nodeContentRef); // Update the Refresh component related parameters. refresh->handle_ = handle; refresh->env_ = g_env; refresh->componentContent_ = componentContentRef; refresh->nodeContent_ = nodeContentRef; refresh->contentHandle_ = contentHandle; refresh->attribute_ = attribute; return refresh; } // Implementation of the update function. void ArkUIMixedRefresh::FlushMixedModeCmd() { napi_handle_scope scope; napi_open_handle_scope(g_env, &scope); // Create the input parameters for the call to the ArkTS API. auto refreshAttribute = CreateRefreshAttribute(attribute_, this); if (refreshAttribute == nullptr) { napi_close_handle_scope(g_env, scope); return; } // Obtain the remaining two API parameters for the update API. napi_value componentContent = nullptr; napi_get_reference_value(g_env, componentContent_, &componentContent); napi_value nodeContent = nullptr; napi_get_reference_value(g_env, nodeContent_, &nodeContent); napi_value argv[3] = {componentContent, nodeContent, refreshAttribute}; napi_value updateRefresh = nullptr; napi_get_reference_value(g_env, g_updateRefresh, &updateRefresh); // Call the ArkTS Update function to update. napi_value result = nullptr; napi_call_function(g_env, nullptr, updateRefresh, 3, argv, &result); } napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); g_env = env; napi_ref refer; napi_create_reference(env, args[0], 1, &refer); g_createRefresh = refer; return nullptr; } napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); g_env = env; napi_ref refer; napi_create_reference(env, args[0], 1, &refer); g_updateRefresh = refer; return nullptr; } } // namespace NativeModule ``` 6. 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. ```c // MixedRefreshExample.h // Sample code for mixed mode. #ifndef MYAPPLICATION_MIXEDREFRESHEXAMPLE_H #define MYAPPLICATION_MIXEDREFRESHEXAMPLE_H #include "ArkUIBaseNode.h" #include "ArkUIMixedRefresh.h" #include "TextListExample.h" #include "UITimer.h" #include <js_native_api_types.h> namespace NativeModule { std::shared_ptr<ArkUIBaseNode> CreateMixedRefreshList(napi_env env) { auto list = CreateTextListExample(); // Create the Refresh component in mixed mode and mount the List component. NativeRefreshAttribute nativeRefreshAttribute{ .backgroundColor = 0xFF89CFF0, .refreshOffset = 64, .pullToRefresh = true}; auto refresh = ArkUIMixedRefresh::Create(nativeRefreshAttribute); refresh->AddChild(list); // Set the event for mixed mode. refresh->SetOnOffsetChange( [](float offset) { OH_LOG_INFO(LOG_APP, "on refresh offset changed: %{public}f", offset); }); refresh->SetRefreshCallback([refreshPtr = refresh.get(), env]() { OH_LOG_INFO(LOG_APP, "on refreshing"); // Start the timer to simulate data acquisition. CreateNativeTimer(env, refreshPtr, 1, [](void *userData, int32_t count) { // Disable the refresh feature after data is obtained. auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(userData); refresh->SetRefreshState(false); refresh->FlushMixedModeCmd(); }); }); // Update the event to the ArkTS side. refresh->FlushMixedModeCmd(); return refresh; } } // namespace NativeModule #endif // MYAPPLICATION_MIXEDREFRESHEXAMPLE_H ``` Replace the entry component creation with the pull-to-refresh text list. ```c #include "NativeEntry.h" #include "ArkUIMixedRefresh.h" #include "MixedRefreshExample.h" #include "TextListExample.h" #include <arkui/native_node_napi.h> #include <arkui/native_type.h> #include <js_native_api.h> #include <uv.h> namespace NativeModule { napi_value CreateNativeRoot(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args[1] = {nullptr}; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); // Obtain NodeContent. ArkUI_NodeContentHandle contentHandle; OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); NativeEntry::GetInstance()->SetContentHandle(contentHandle); // Create a Refresh text list. auto refresh = CreateMixedRefreshList(env); // Keep the native side object in the management class to maintain its lifecycle. NativeEntry::GetInstance()->SetRootNode(refresh); return nullptr; } napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) { // Release the native side object from the management class. NativeEntry::GetInstance()->DisposeRootNode(); return nullptr; } } // namespace NativeModule ```