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  ![en-us_image_0000001949769409](figures/en-us_image_0000001949769409.png)
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