1e41f4b71Sopenharmony_ci# Developing a Long List with Lazy Loading 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ciFor the **List**, **Grid**, **WaterFlow**, and **Swiper** components, the [NodeAdapter](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadapterhandle) object is provided as an alternative to the ArkTS **LazyForEach** feature for on-demand child component generation. The specific attribute enumeration values are as follows: 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci- **List**: **NODE_LIST_NODE_ADAPTER** 6e41f4b71Sopenharmony_ci- **Grid**: **NODE_GRID_NODE_ADAPTER** 7e41f4b71Sopenharmony_ci- **WaterFlow**: **NODE_WATER_FLOW_NODE_ADAPTER** 8e41f4b71Sopenharmony_ci- **Swiper**: **NODE_SWIPER_NODE_ADAPTER** 9e41f4b71Sopenharmony_ci 10e41f4b71Sopenharmony_ciKey specifications of **NodeAdapter** include: 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci- Nodes with **NodeAdapter** set do not support direct child addition APIs like **addChild**. Child components are managed entirely by **NodeAdapter**. If a parent component already has child nodes, setting **NodeAdapter** will fail and return an error code. 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci- **NodeAdapter** uses events to notify you to generate components on demand. You must register an [event listener](../reference/apis-arkui/_ark_u_i___native_module.md#oh_arkui_nodeadapter_registereventreceiver) and handle logic within listener events, which are defined by [ArkUI_NodeAdapterEventType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadaptereventtype). **NodeAdapter** does not automatically release off-screen component objects; you must manage object release or caching during the [NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadaptereventtype) event. The following image illustrates the event triggering mechanism in a typical list scrolling scenario. 16e41f4b71Sopenharmony_ci  17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ciThe following example optimizes the code in the [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md) section, by introducing a lazy loading mechanism for a text list: 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci1. Integrate ArkTS into your project. For details, see [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md). 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci2. Implement lazy loading adapter functionality. 25e41f4b71Sopenharmony_ci ``` 26e41f4b71Sopenharmony_ci // ArkUIListItemAdapter 27e41f4b71Sopenharmony_ci // Code for lazy loading functionality in a text list. 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_ARKUILISTITEMADAPTER_H 30e41f4b71Sopenharmony_ci #define MYAPPLICATION_ARKUILISTITEMADAPTER_H 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci #include <arkui/native_node.h> 33e41f4b71Sopenharmony_ci #include <stack> 34e41f4b71Sopenharmony_ci #include <string> 35e41f4b71Sopenharmony_ci #include <unordered_set> 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci #include "ArkUIListItemNode.h" 38e41f4b71Sopenharmony_ci #include "ArkUITextNode.h" 39e41f4b71Sopenharmony_ci #include "nativeModule.h" 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ci namespace NativeModule { 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ci class ArkUIListItemAdapter { 44e41f4b71Sopenharmony_ci public: 45e41f4b71Sopenharmony_ci ArkUIListItemAdapter() 46e41f4b71Sopenharmony_ci : module_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()), handle_(OH_ArkUI_NodeAdapter_Create()) { // Use the NodeAdapter creation function. 47e41f4b71Sopenharmony_ci // Initialize lazy loading data. 48e41f4b71Sopenharmony_ci for (int32_t i = 0; i < 1000; i++) { 49e41f4b71Sopenharmony_ci data_.emplace_back(std::to_string(i)); 50e41f4b71Sopenharmony_ci } 51e41f4b71Sopenharmony_ci // Set lazy loading data. 52e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); 53e41f4b71Sopenharmony_ci // Register the event receiver for lazy loading. 54e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_RegisterEventReceiver(handle_, this, OnStaticAdapterEvent); 55e41f4b71Sopenharmony_ci } 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci ~ArkUIListItemAdapter() { 58e41f4b71Sopenharmony_ci // Release created components. 59e41f4b71Sopenharmony_ci while (!cachedItems_.empty()) { 60e41f4b71Sopenharmony_ci cachedItems_.pop(); 61e41f4b71Sopenharmony_ci } 62e41f4b71Sopenharmony_ci items_.clear(); 63e41f4b71Sopenharmony_ci // Release adapter resources. 64e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_UnregisterEventReceiver(handle_); 65e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_Dispose(handle_); 66e41f4b71Sopenharmony_ci } 67e41f4b71Sopenharmony_ci 68e41f4b71Sopenharmony_ci ArkUI_NodeAdapterHandle GetHandle() const { return handle_; } 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci void RemoveItem(int32_t index) { 71e41f4b71Sopenharmony_ci // Remove the item at the specified index. 72e41f4b71Sopenharmony_ci data_.erase(data_.begin() + index); 73e41f4b71Sopenharmony_ci // If the index change affects the visibility of items in the visible area, the NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER event will be triggered to remove the element. 74e41f4b71Sopenharmony_ci // If items are added, the NODE_ADAPTER_EVENT_ON_GET_NODE_ID and NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER events will be triggered accordingly. 75e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1); 76e41f4b71Sopenharmony_ci // Update the new total count. 77e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); 78e41f4b71Sopenharmony_ci } 79e41f4b71Sopenharmony_ci 80e41f4b71Sopenharmony_ci void InsertItem(int32_t index, const std::string &value) { 81e41f4b71Sopenharmony_ci data_.insert(data_.begin() + index, value); 82e41f4b71Sopenharmony_ci // If the index change affects the visibility of elements in the visible area, the NODE_ADAPTER_EVENT_ON_GET_NODE_ID and NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER events will be triggered. 83e41f4b71Sopenharmony_ci // If items are removed, the NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER event will be triggered accordingly. 84e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_InsertItem(handle_, index, 1); 85e41f4b71Sopenharmony_ci // Update the new total count. 86e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); 87e41f4b71Sopenharmony_ci } 88e41f4b71Sopenharmony_ci 89e41f4b71Sopenharmony_ci void MoveItem(int32_t oldIndex, int32_t newIndex) { 90e41f4b71Sopenharmony_ci auto temp = data_[oldIndex]; 91e41f4b71Sopenharmony_ci data_.insert(data_.begin() + newIndex, temp); 92e41f4b71Sopenharmony_ci data_.erase(data_.begin() + oldIndex); 93e41f4b71Sopenharmony_ci // If the move changes the visibility of items within the visible area, the corresponding events will be triggered. 94e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_MoveItem(handle_, oldIndex, newIndex); 95e41f4b71Sopenharmony_ci } 96e41f4b71Sopenharmony_ci 97e41f4b71Sopenharmony_ci void ReloadItem(int32_t index, const std::string &value) { 98e41f4b71Sopenharmony_ci data_[index] = value; 99e41f4b71Sopenharmony_ci // If the index is within the visible area, first trigger the NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER event to remove the old item, 100e41f4b71Sopenharmony_ci // then trigger the NODE_ADAPTER_EVENT_ON_GET_NODE_ID and NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER events. 101e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_ReloadItem(handle_, index, 1); 102e41f4b71Sopenharmony_ci } 103e41f4b71Sopenharmony_ci 104e41f4b71Sopenharmony_ci void ReloadAllItem() { 105e41f4b71Sopenharmony_ci std::reverse(data_.begin(), data_.end()); 106e41f4b71Sopenharmony_ci // In the scenario where all items are reloaded, the NODE_ADAPTER_EVENT_ON_GET_NODE_ID event will be triggered to obtain new component IDs, 107e41f4b71Sopenharmony_ci // compare the new component IDs, and reuse those whose IDs have not changed, 108e41f4b71Sopenharmony_ci // for items with new IDs, trigger the NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER event to create new components, 109e41f4b71Sopenharmony_ci // then identify any unused IDs from the old data and call NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER to remove the old items. 110e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapter_ReloadAllItems(handle_); 111e41f4b71Sopenharmony_ci } 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ci private: 114e41f4b71Sopenharmony_ci static void OnStaticAdapterEvent(ArkUI_NodeAdapterEvent *event) { 115e41f4b71Sopenharmony_ci // Obtain the instance object and invoke its event callback. 116e41f4b71Sopenharmony_ci auto itemAdapter = reinterpret_cast<ArkUIListItemAdapter *>(OH_ArkUI_NodeAdapterEvent_GetUserData(event)); 117e41f4b71Sopenharmony_ci itemAdapter->OnAdapterEvent(event); 118e41f4b71Sopenharmony_ci } 119e41f4b71Sopenharmony_ci 120e41f4b71Sopenharmony_ci void OnAdapterEvent(ArkUI_NodeAdapterEvent *event) { 121e41f4b71Sopenharmony_ci auto type = OH_ArkUI_NodeAdapterEvent_GetType(event); 122e41f4b71Sopenharmony_ci switch (type) { 123e41f4b71Sopenharmony_ci case NODE_ADAPTER_EVENT_ON_GET_NODE_ID: 124e41f4b71Sopenharmony_ci OnNewItemIdCreated(event); 125e41f4b71Sopenharmony_ci break; 126e41f4b71Sopenharmony_ci case NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER: 127e41f4b71Sopenharmony_ci OnNewItemAttached(event); 128e41f4b71Sopenharmony_ci break; 129e41f4b71Sopenharmony_ci case NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER: 130e41f4b71Sopenharmony_ci OnItemDetached(event); 131e41f4b71Sopenharmony_ci break; 132e41f4b71Sopenharmony_ci default: 133e41f4b71Sopenharmony_ci break; 134e41f4b71Sopenharmony_ci } 135e41f4b71Sopenharmony_ci } 136e41f4b71Sopenharmony_ci 137e41f4b71Sopenharmony_ci // Assign IDs to items that need to be displayed, used for element diffing in the ReloadAllItems scenario. 138e41f4b71Sopenharmony_ci void OnNewItemIdCreated(ArkUI_NodeAdapterEvent *event) { 139e41f4b71Sopenharmony_ci auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event); 140e41f4b71Sopenharmony_ci static std::hash<std::string> hashId = std::hash<std::string>(); 141e41f4b71Sopenharmony_ci auto id = hashId(data_[index]); 142e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapterEvent_SetNodeId(event, id); 143e41f4b71Sopenharmony_ci } 144e41f4b71Sopenharmony_ci 145e41f4b71Sopenharmony_ci // Handle the display of new items in the visible area. 146e41f4b71Sopenharmony_ci void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) { 147e41f4b71Sopenharmony_ci auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event); 148e41f4b71Sopenharmony_ci ArkUI_NodeHandle handle = nullptr; 149e41f4b71Sopenharmony_ci if (!cachedItems_.empty()) { 150e41f4b71Sopenharmony_ci // Use and update the recycled item from the cache. 151e41f4b71Sopenharmony_ci auto recycledItem = cachedItems_.top(); 152e41f4b71Sopenharmony_ci auto textItem = std::dynamic_pointer_cast<ArkUITextNode>(recycledItem->GetChildren().back()); 153e41f4b71Sopenharmony_ci textItem->SetTextContent(data_[index]); 154e41f4b71Sopenharmony_ci handle = recycledItem->GetHandle(); 155e41f4b71Sopenharmony_ci // Release the reference from the cache. 156e41f4b71Sopenharmony_ci cachedItems_.pop(); 157e41f4b71Sopenharmony_ci } else { 158e41f4b71Sopenharmony_ci // Create a new item. 159e41f4b71Sopenharmony_ci auto listItem = std::make_shared<ArkUIListItemNode>(); 160e41f4b71Sopenharmony_ci auto textNode = std::make_shared<ArkUITextNode>(); 161e41f4b71Sopenharmony_ci textNode->SetTextContent(data_[index]); 162e41f4b71Sopenharmony_ci textNode->SetFontSize(16); 163e41f4b71Sopenharmony_ci textNode->SetPercentWidth(1); 164e41f4b71Sopenharmony_ci textNode->SetHeight(100); 165e41f4b71Sopenharmony_ci textNode->SetBackgroundColor(0xFFfffacd); 166e41f4b71Sopenharmony_ci textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER); 167e41f4b71Sopenharmony_ci listItem->AddChild(textNode); 168e41f4b71Sopenharmony_ci listItem->RegisterOnClick([index]() { OH_LOG_INFO(LOG_APP, "on %{public}d list item click", index); }); 169e41f4b71Sopenharmony_ci handle = listItem->GetHandle(); 170e41f4b71Sopenharmony_ci // Keep a reference to the text list item. 171e41f4b71Sopenharmony_ci items_.emplace(handle, listItem); 172e41f4b71Sopenharmony_ci } 173e41f4b71Sopenharmony_ci // Set the item to be displayed. 174e41f4b71Sopenharmony_ci OH_ArkUI_NodeAdapterEvent_SetItem(event, handle); 175e41f4b71Sopenharmony_ci } 176e41f4b71Sopenharmony_ci 177e41f4b71Sopenharmony_ci // Remove an item from the visible area. 178e41f4b71Sopenharmony_ci void OnItemDetached(ArkUI_NodeAdapterEvent *event) { 179e41f4b71Sopenharmony_ci auto item = OH_ArkUI_NodeAdapterEvent_GetRemovedNode(event); 180e41f4b71Sopenharmony_ci // Place the item in the cache pool for recycling and reuse. 181e41f4b71Sopenharmony_ci cachedItems_.emplace(items_[item]); 182e41f4b71Sopenharmony_ci } 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci 185e41f4b71Sopenharmony_ci std::vector<std::string> data_; 186e41f4b71Sopenharmony_ci ArkUI_NativeNodeAPI_1 *module_ = nullptr; 187e41f4b71Sopenharmony_ci ArkUI_NodeAdapterHandle handle_ = nullptr; 188e41f4b71Sopenharmony_ci 189e41f4b71Sopenharmony_ci // Manage items generated by the NodeAdapter. 190e41f4b71Sopenharmony_ci std::unordered_map<ArkUI_NodeHandle, std::shared_ptr<ArkUIListItemNode>> items_; 191e41f4b71Sopenharmony_ci 192e41f4b71Sopenharmony_ci // Manage the component reuse pool. 193e41f4b71Sopenharmony_ci std::stack<std::shared_ptr<ArkUIListItemNode>> cachedItems_; 194e41f4b71Sopenharmony_ci }; 195e41f4b71Sopenharmony_ci 196e41f4b71Sopenharmony_ci } // namespace NativeModule 197e41f4b71Sopenharmony_ci 198e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_ARKUILISTITEMADAPTER_H 199e41f4b71Sopenharmony_ci ``` 200e41f4b71Sopenharmony_ci 201e41f4b71Sopenharmony_ci3. Enhance the encapsulated list class object used in the [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md) section with additional lazy loading capabilities. 202e41f4b71Sopenharmony_ci ``` 203e41f4b71Sopenharmony_ci // ArkUIListNode.h 204e41f4b71Sopenharmony_ci // Encapsulated list class object. 205e41f4b71Sopenharmony_ci 206e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_ARKUILISTNODE_H 207e41f4b71Sopenharmony_ci #define MYAPPLICATION_ARKUILISTNODE_H 208e41f4b71Sopenharmony_ci 209e41f4b71Sopenharmony_ci #include "ArkUIListItemAdapter.h" 210e41f4b71Sopenharmony_ci #include "ArkUINode.h" 211e41f4b71Sopenharmony_ci #include <hilog/log.h> 212e41f4b71Sopenharmony_ci 213e41f4b71Sopenharmony_ci namespace NativeModule { 214e41f4b71Sopenharmony_ci class ArkUIListNode : public ArkUINode { 215e41f4b71Sopenharmony_ci public: 216e41f4b71Sopenharmony_ci ArkUIListNode() 217e41f4b71Sopenharmony_ci : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {} 218e41f4b71Sopenharmony_ci 219e41f4b71Sopenharmony_ci ~ArkUIListNode() override { 220e41f4b71Sopenharmony_ci nativeModule_->unregisterNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX); 221e41f4b71Sopenharmony_ci if (adapter_) { 222e41f4b71Sopenharmony_ci // Unmount UI components associated with the adapter upon destruction. 223e41f4b71Sopenharmony_ci nativeModule_->resetAttribute(handle_, NODE_LIST_NODE_ADAPTER); 224e41f4b71Sopenharmony_ci adapter_.reset(); 225e41f4b71Sopenharmony_ci } 226e41f4b71Sopenharmony_ci } 227e41f4b71Sopenharmony_ci 228e41f4b71Sopenharmony_ci void SetScrollBarState(bool isShow) { 229e41f4b71Sopenharmony_ci assert(handle_); 230e41f4b71Sopenharmony_ci ArkUI_ScrollBarDisplayMode displayMode = 231e41f4b71Sopenharmony_ci isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF; 232e41f4b71Sopenharmony_ci ArkUI_NumberValue value[] = {{.i32 = displayMode}}; 233e41f4b71Sopenharmony_ci ArkUI_AttributeItem item = {value, 1}; 234e41f4b71Sopenharmony_ci nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item); 235e41f4b71Sopenharmony_ci } 236e41f4b71Sopenharmony_ci 237e41f4b71Sopenharmony_ci void RegisterOnScrollIndex(const std::function<void(int32_t index)> &onScrollIndex) { 238e41f4b71Sopenharmony_ci assert(handle_); 239e41f4b71Sopenharmony_ci onScrollIndex_ = onScrollIndex; 240e41f4b71Sopenharmony_ci nativeModule_->registerNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX, 0, nullptr); 241e41f4b71Sopenharmony_ci } 242e41f4b71Sopenharmony_ci // Import the lazy loading module. 243e41f4b71Sopenharmony_ci void SetLazyAdapter(const std::shared_ptr<ArkUIListItemAdapter> &adapter) { 244e41f4b71Sopenharmony_ci assert(handle_); 245e41f4b71Sopenharmony_ci ArkUI_AttributeItem item{nullptr, 0, nullptr, adapter->GetHandle()}; 246e41f4b71Sopenharmony_ci nativeModule_->setAttribute(handle_, NODE_LIST_NODE_ADAPTER, &item); 247e41f4b71Sopenharmony_ci adapter_ = adapter; 248e41f4b71Sopenharmony_ci } 249e41f4b71Sopenharmony_ci 250e41f4b71Sopenharmony_ci protected: 251e41f4b71Sopenharmony_ci void OnNodeEvent(ArkUI_NodeEvent *event) override { 252e41f4b71Sopenharmony_ci auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); 253e41f4b71Sopenharmony_ci switch (eventType) { 254e41f4b71Sopenharmony_ci case NODE_LIST_ON_SCROLL_INDEX: { 255e41f4b71Sopenharmony_ci auto index = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event)->data[0]; 256e41f4b71Sopenharmony_ci if (onScrollIndex_) { 257e41f4b71Sopenharmony_ci onScrollIndex_(index.i32); 258e41f4b71Sopenharmony_ci } 259e41f4b71Sopenharmony_ci } 260e41f4b71Sopenharmony_ci default: { 261e41f4b71Sopenharmony_ci } 262e41f4b71Sopenharmony_ci } 263e41f4b71Sopenharmony_ci } 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci private: 266e41f4b71Sopenharmony_ci std::function<void(int32_t index)> onScrollIndex_; 267e41f4b71Sopenharmony_ci 268e41f4b71Sopenharmony_ci std::shared_ptr<ArkUIListItemAdapter> adapter_; 269e41f4b71Sopenharmony_ci }; 270e41f4b71Sopenharmony_ci } // namespace NativeModule 271e41f4b71Sopenharmony_ci 272e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_ARKUILISTNODE_H 273e41f4b71Sopenharmony_ci ``` 274e41f4b71Sopenharmony_ci 275e41f4b71Sopenharmony_ci4. Write code for lazy loading of a list. 276e41f4b71Sopenharmony_ci ``` 277e41f4b71Sopenharmony_ci // ArkUILazyTextListExample 278e41f4b71Sopenharmony_ci // Sample code for lazy loading a list. 279e41f4b71Sopenharmony_ci 280e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H 281e41f4b71Sopenharmony_ci #define MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H 282e41f4b71Sopenharmony_ci 283e41f4b71Sopenharmony_ci #include "ArkUIBaseNode.h" 284e41f4b71Sopenharmony_ci #include "ArkUIListNode.h" 285e41f4b71Sopenharmony_ci #include "UITimer.h" 286e41f4b71Sopenharmony_ci #include <thread> 287e41f4b71Sopenharmony_ci #include <uv.h> 288e41f4b71Sopenharmony_ci 289e41f4b71Sopenharmony_ci namespace NativeModule { 290e41f4b71Sopenharmony_ci 291e41f4b71Sopenharmony_ci std::shared_ptr<ArkUIBaseNode> CreateLazyTextListExample(napi_env env) { 292e41f4b71Sopenharmony_ci // Create components and mount them. 293e41f4b71Sopenharmony_ci // 1: Create a List component. 294e41f4b71Sopenharmony_ci auto list = std::make_shared<ArkUIListNode>(); 295e41f4b71Sopenharmony_ci list->SetPercentWidth(1); 296e41f4b71Sopenharmony_ci list->SetPercentHeight(1); 297e41f4b71Sopenharmony_ci // 2: Create ListItem child components for lazy loading and mount them to the List component. 298e41f4b71Sopenharmony_ci auto adapter = std::make_shared<ArkUIListItemAdapter>(); 299e41f4b71Sopenharmony_ci list->SetLazyAdapter(adapter); 300e41f4b71Sopenharmony_ci 301e41f4b71Sopenharmony_ci // 3: Simulate lazy loading operations. 302e41f4b71Sopenharmony_ci CreateNativeTimer(env, adapter.get(), 4, [](void *userdata, int32_t count) { 303e41f4b71Sopenharmony_ci auto adapter = reinterpret_cast<ArkUIListItemAdapter *>(userdata); 304e41f4b71Sopenharmony_ci switch (count) { 305e41f4b71Sopenharmony_ci case 0: { 306e41f4b71Sopenharmony_ci // Remove the 0th item. 307e41f4b71Sopenharmony_ci adapter->RemoveItem(0); 308e41f4b71Sopenharmony_ci break; 309e41f4b71Sopenharmony_ci } 310e41f4b71Sopenharmony_ci case 1: { 311e41f4b71Sopenharmony_ci // Insert the 0th item. 312e41f4b71Sopenharmony_ci adapter->InsertItem(0, "0"); 313e41f4b71Sopenharmony_ci break; 314e41f4b71Sopenharmony_ci } 315e41f4b71Sopenharmony_ci case 2: { 316e41f4b71Sopenharmony_ci // Move an item to a new position. 317e41f4b71Sopenharmony_ci adapter->MoveItem(0, 2); 318e41f4b71Sopenharmony_ci break; 319e41f4b71Sopenharmony_ci } 320e41f4b71Sopenharmony_ci case 3: { 321e41f4b71Sopenharmony_ci // Reload a single item. 322e41f4b71Sopenharmony_ci adapter->ReloadItem(0, "1112"); 323e41f4b71Sopenharmony_ci break; 324e41f4b71Sopenharmony_ci } 325e41f4b71Sopenharmony_ci case 4: { 326e41f4b71Sopenharmony_ci // Reload all items. 327e41f4b71Sopenharmony_ci adapter->ReloadAllItem(); 328e41f4b71Sopenharmony_ci break; 329e41f4b71Sopenharmony_ci } 330e41f4b71Sopenharmony_ci default: { 331e41f4b71Sopenharmony_ci } 332e41f4b71Sopenharmony_ci } 333e41f4b71Sopenharmony_ci }); 334e41f4b71Sopenharmony_ci 335e41f4b71Sopenharmony_ci // 3: Register list-related listening events. 336e41f4b71Sopenharmony_ci list->RegisterOnScrollIndex([](int32_t index) { OH_LOG_INFO(LOG_APP, "on list scroll index: %{public}d", index); }); 337e41f4b71Sopenharmony_ci // 4: Register the appear event. 338e41f4b71Sopenharmony_ci list->RegisterOnAppear([]() { OH_LOG_INFO(LOG_APP, "on list mount to tree"); }); 339e41f4b71Sopenharmony_ci // 4: Register the disappear event. 340e41f4b71Sopenharmony_ci list->RegisterOnDisappear([]() { OH_LOG_INFO(LOG_APP, "on list unmount from tree"); }); 341e41f4b71Sopenharmony_ci return list; 342e41f4b71Sopenharmony_ci } 343e41f4b71Sopenharmony_ci } // namespace NativeModule 344e41f4b71Sopenharmony_ci 345e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H 346e41f4b71Sopenharmony_ci ``` 347e41f4b71Sopenharmony_ci 348e41f4b71Sopenharmony_ci5. Implement a simple timer module. 349e41f4b71Sopenharmony_ci ``` 350e41f4b71Sopenharmony_ci // UITimer.h 351e41f4b71Sopenharmony_ci // Timer module. 352e41f4b71Sopenharmony_ci 353e41f4b71Sopenharmony_ci #ifndef MYAPPLICATION_UITIMER_H 354e41f4b71Sopenharmony_ci #define MYAPPLICATION_UITIMER_H 355e41f4b71Sopenharmony_ci 356e41f4b71Sopenharmony_ci #include <hilog/log.h> 357e41f4b71Sopenharmony_ci #include <js_native_api.h> 358e41f4b71Sopenharmony_ci #include <js_native_api_types.h> 359e41f4b71Sopenharmony_ci #include <node_api.h> 360e41f4b71Sopenharmony_ci #include <node_api_types.h> 361e41f4b71Sopenharmony_ci #include <string> 362e41f4b71Sopenharmony_ci #include <thread> 363e41f4b71Sopenharmony_ci #include <uv.h> 364e41f4b71Sopenharmony_ci 365e41f4b71Sopenharmony_ci namespace NativeModule { 366e41f4b71Sopenharmony_ci 367e41f4b71Sopenharmony_ci struct UIData { 368e41f4b71Sopenharmony_ci void *userData = nullptr; 369e41f4b71Sopenharmony_ci int32_t count = 0; 370e41f4b71Sopenharmony_ci int32_t totalCount = 0; 371e41f4b71Sopenharmony_ci void (*func)(void *userData, int32_t count) = nullptr; 372e41f4b71Sopenharmony_ci }; 373e41f4b71Sopenharmony_ci 374e41f4b71Sopenharmony_ci napi_threadsafe_function threadSafeFunction = nullptr; 375e41f4b71Sopenharmony_ci 376e41f4b71Sopenharmony_ci void CreateNativeTimer(napi_env env, void *userData, int32_t totalCount, void (*func)(void *userData, int32_t count)) { 377e41f4b71Sopenharmony_ci napi_value name; 378e41f4b71Sopenharmony_ci std::string str = "UICallback"; 379e41f4b71Sopenharmony_ci napi_create_string_utf8(env, str.c_str(), str.size(), &name); 380e41f4b71Sopenharmony_ci // UI main thread callback function. 381e41f4b71Sopenharmony_ci napi_create_threadsafe_function( 382e41f4b71Sopenharmony_ci env, nullptr, nullptr, name, 0, 1, nullptr, nullptr, nullptr, 383e41f4b71Sopenharmony_ci [](napi_env env, napi_value value, void *context, void *data) { 384e41f4b71Sopenharmony_ci auto userdata = reinterpret_cast<UIData *>(data); 385e41f4b71Sopenharmony_ci userdata->func(userdata->userData, userdata->count); 386e41f4b71Sopenharmony_ci delete userdata; 387e41f4b71Sopenharmony_ci }, 388e41f4b71Sopenharmony_ci &threadSafeFunction); 389e41f4b71Sopenharmony_ci // Start the timer to simulate data changes. 390e41f4b71Sopenharmony_ci std::thread timerThread([data = userData, totalCount, func]() { 391e41f4b71Sopenharmony_ci uv_loop_t *loop = uv_loop_new(); 392e41f4b71Sopenharmony_ci uv_timer_t *timer = new uv_timer_t(); 393e41f4b71Sopenharmony_ci uv_timer_init(loop, timer); 394e41f4b71Sopenharmony_ci timer->data = new UIData{data, 0, totalCount, func}; 395e41f4b71Sopenharmony_ci uv_timer_start( 396e41f4b71Sopenharmony_ci timer, 397e41f4b71Sopenharmony_ci [](uv_timer_t *handle) { 398e41f4b71Sopenharmony_ci OH_LOG_INFO(LOG_APP, "on timeout"); 399e41f4b71Sopenharmony_ci napi_acquire_threadsafe_function(threadSafeFunction); 400e41f4b71Sopenharmony_ci auto *customData = reinterpret_cast<UIData *>(handle->data); 401e41f4b71Sopenharmony_ci // Create callback data. 402e41f4b71Sopenharmony_ci auto *callbackData = 403e41f4b71Sopenharmony_ci new UIData{customData->userData, customData->count, customData->totalCount, customData->func}; 404e41f4b71Sopenharmony_ci napi_call_threadsafe_function(threadSafeFunction, callbackData, napi_tsfn_blocking); 405e41f4b71Sopenharmony_ci customData->count++; 406e41f4b71Sopenharmony_ci if (customData->count > customData->totalCount) { 407e41f4b71Sopenharmony_ci uv_timer_stop(handle); 408e41f4b71Sopenharmony_ci delete handle; 409e41f4b71Sopenharmony_ci delete customData; 410e41f4b71Sopenharmony_ci } 411e41f4b71Sopenharmony_ci }, 412e41f4b71Sopenharmony_ci 4000, 4000); 413e41f4b71Sopenharmony_ci uv_run(loop, UV_RUN_DEFAULT); 414e41f4b71Sopenharmony_ci uv_loop_delete(loop); 415e41f4b71Sopenharmony_ci }); 416e41f4b71Sopenharmony_ci timerThread.detach(); 417e41f4b71Sopenharmony_ci } 418e41f4b71Sopenharmony_ci } // namespace NativeModule 419e41f4b71Sopenharmony_ci 420e41f4b71Sopenharmony_ci #endif // MYAPPLICATION_UITIMER_H 421e41f4b71Sopenharmony_ci ``` 422e41f4b71Sopenharmony_ci 423e41f4b71Sopenharmony_ci6. Mount the lazy loading example code onto the **ContentSlot** as described in the [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md) section. 424e41f4b71Sopenharmony_ci ``` 425e41f4b71Sopenharmony_ci // NDK API entry mount file. 426e41f4b71Sopenharmony_ci 427e41f4b71Sopenharmony_ci #include "NativeEntry.h" 428e41f4b71Sopenharmony_ci 429e41f4b71Sopenharmony_ci #include "ArkUIMixedRefresh.h" 430e41f4b71Sopenharmony_ci #include "LazyTextListExample.h" 431e41f4b71Sopenharmony_ci #include "MixedRefreshExample.h" 432e41f4b71Sopenharmony_ci #include "TextListExample.h" 433e41f4b71Sopenharmony_ci 434e41f4b71Sopenharmony_ci #include <arkui/native_node_napi.h> 435e41f4b71Sopenharmony_ci #include <arkui/native_type.h> 436e41f4b71Sopenharmony_ci #include <js_native_api.h> 437e41f4b71Sopenharmony_ci #include <uv.h> 438e41f4b71Sopenharmony_ci 439e41f4b71Sopenharmony_ci namespace NativeModule { 440e41f4b71Sopenharmony_ci namespace { 441e41f4b71Sopenharmony_ci napi_env g_env; 442e41f4b71Sopenharmony_ci } 443e41f4b71Sopenharmony_ci 444e41f4b71Sopenharmony_ci napi_env GetNapiEnv() { return g_env; } 445e41f4b71Sopenharmony_ci 446e41f4b71Sopenharmony_ci napi_value CreateNativeRoot(napi_env env, napi_callback_info info) { 447e41f4b71Sopenharmony_ci size_t argc = 1; 448e41f4b71Sopenharmony_ci napi_value args[1] = {nullptr}; 449e41f4b71Sopenharmony_ci 450e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 451e41f4b71Sopenharmony_ci 452e41f4b71Sopenharmony_ci // Obtain NodeContent. 453e41f4b71Sopenharmony_ci ArkUI_NodeContentHandle contentHandle; 454e41f4b71Sopenharmony_ci OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle); 455e41f4b71Sopenharmony_ci NativeEntry::GetInstance()->SetContentHandle(contentHandle); 456e41f4b71Sopenharmony_ci 457e41f4b71Sopenharmony_ci // Create a lazy-loaded text list. 458e41f4b71Sopenharmony_ci auto node = CreateLazyTextListExample(env); 459e41f4b71Sopenharmony_ci 460e41f4b71Sopenharmony_ci // Keep the native side object in the management class to maintain its lifecycle. 461e41f4b71Sopenharmony_ci NativeEntry::GetInstance()->SetRootNode(node); 462e41f4b71Sopenharmony_ci g_env = env; 463e41f4b71Sopenharmony_ci return nullptr; 464e41f4b71Sopenharmony_ci } 465e41f4b71Sopenharmony_ci 466e41f4b71Sopenharmony_ci napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) { 467e41f4b71Sopenharmony_ci // Release the native side object from the management class. 468e41f4b71Sopenharmony_ci NativeEntry::GetInstance()->DisposeRootNode(); 469e41f4b71Sopenharmony_ci return nullptr; 470e41f4b71Sopenharmony_ci } 471e41f4b71Sopenharmony_ci 472e41f4b71Sopenharmony_ci } // namespace NativeModule 473e41f4b71Sopenharmony_ci ``` 474