• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用列表
2
3<!--Kit: ArkUI-->
4<!--Subsystem: ArkUI-->
5<!--Owner: @yylong-->
6<!--Designer: @yylong-->
7<!--Tester: @liuzhenshuo-->
8<!--Adviser: @HelloCrease-->
9
10ArkUI开发框架在NDK接口提供了列表组件,使用列表可以轻松高效地显示结构化、可滚动的信息。列表组件支持控制滚动位置、支持分组显示内容、支持使用NodeAdapter实现懒加载以提升列表创建性能。
11
12## 创建列表
13
14参考[接入ArkTS页面章节](../ui/ndk-access-the-arkts-page.md)实现列表创建。
15
16## 监听滚动事件
17
18参考[监听组件事件](ndk-listen-to-component-events.md)章节实现列表滚动事件监听。
19
20## 使用懒加载
21
22### NodeAdapter介绍
23
24NDK提供了[NodeAdapter](../reference/apis-arkui/capi-arkui-nativemodule-arkui-nodeadapter8h.md)对象替代ArkTS侧的LazyForEach功能,用于按需生成子组件,NodeAdapter支持在List/ListItemGroup、Grid、WaterFlow、Swiper组件中使用。
25
26- 设置了NodeAdapter属性的节点,不再支持addChild等直接添加子组件的接口。子组件完全由NodeAdapter管理,使用属性方法设置NodeAdapter时,会判断父组件是否已经存在子节点,如果父组件已经存在子节点,则设置NodeAdapter操作失败,返回错误码。
27
28- NodeAdapter通过相关事件通知开发者按需生成组件,类似组件事件机制,开发者使用NodeAdapter时要注册[事件监听器](../reference/apis-arkui/capi-native-node-h.md#oh_arkui_nodeadapter_registereventreceiver),在监听器事件中处理逻辑,相关事件通过[ArkUI_NodeAdapterEventType](../reference/apis-arkui/capi-native-node-h.md#arkui_nodeadaptereventtype)定义。另外NodeAdapter不会主动释放不在屏幕内显示的组件对象,开发者需要在[NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER](../reference/apis-arkui/capi-native-node-h.md#arkui_nodeadaptereventtype)事件中进行组件对象的释放,或者进行缓存复用。下图展示了典型列表滑动场景下的事件触发机制:
29  ![zh-cn_image_0000001949769409](figures/zh-cn_image_0000001949769409.png)
30
31
32### 实现懒加载适配器
33
34使用ArkUIListItemAdapter类来管理懒加载适配器,在类的构造中创建NodeAdapter对象,并给NodeAdapter对象设置事件监听器,在类的析构函数中,销毁NodeAdapter对象。
35
36   ```c++
37   // ArkUIListItemAdapter
38   // 用于文本列表懒加载功能代码。
39
40   #ifndef MYAPPLICATION_ARKUILISTITEMADAPTER_H
41   #define MYAPPLICATION_ARKUILISTITEMADAPTER_H
42
43   #include <arkui/native_node.h>
44   #include <stack>
45   #include <string>
46   #include <unordered_set>
47
48   #include "ArkUIListItemNode.h"
49   #include "ArkUITextNode.h"
50   #include "NativeModule.h"
51   #include <hilog/log.h>
52
53   namespace NativeModule {
54
55   class ArkUIListItemAdapter {
56   public:
57       ArkUIListItemAdapter()
58           : module_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()), handle_(OH_ArkUI_NodeAdapter_Create()) { // 使用NodeAdapter创建函数。
59           // 初始化懒加载数据。
60           for (int32_t i = 0; i < 1000; i++) {
61               data_.emplace_back(std::to_string(i));
62           }
63           // 设置懒加载数据。
64           OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
65           // 设置懒加载回调事件。
66           OH_ArkUI_NodeAdapter_RegisterEventReceiver(handle_, this, OnStaticAdapterEvent);
67       }
68
69       ~ArkUIListItemAdapter() {
70           // 释放创建的组件。
71           while (!cachedItems_.empty()) {
72               cachedItems_.pop();
73           }
74           items_.clear();
75           // 释放Adapter相关资源。
76           OH_ArkUI_NodeAdapter_UnregisterEventReceiver(handle_);
77           OH_ArkUI_NodeAdapter_Dispose(handle_);
78       }
79
80       ArkUI_NodeAdapterHandle GetHandle() const { return handle_; }
81
82       void RemoveItem(int32_t index) {
83           // 删除第index个数据。
84           data_.erase(data_.begin() + index);
85           // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件删除元素,
86           // 根据是否有新增元素回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。
87           OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1);
88           // 更新新的数量。
89           OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
90       }
91
92       void InsertItem(int32_t index, const std::string &value) {
93           data_.insert(data_.begin() + index, value);
94           // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件,
95           // 根据是否有删除元素回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件。
96           OH_ArkUI_NodeAdapter_InsertItem(handle_, index, 1);
97           // 更新新的数量。
98           OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
99       }
100
101       void MoveItem(int32_t oldIndex, int32_t newIndex) {
102           auto temp = data_[oldIndex];
103           data_.insert(data_.begin() + newIndex, temp);
104           data_.erase(data_.begin() + oldIndex);
105           // 移到位置如果未发生可视区域内元素的可见性变化,则不回调事件,反之根据新增和删除场景回调对应的事件。
106           OH_ArkUI_NodeAdapter_MoveItem(handle_, oldIndex, newIndex);
107       }
108
109       void ReloadItem(int32_t index, const std::string &value) {
110           data_[index] = value;
111           // 如果index位于可视区域内,先回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER删除老元素,
112           // 再回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。
113           OH_ArkUI_NodeAdapter_ReloadItem(handle_, index, 1);
114       }
115
116       void ReloadAllItem() {
117           std::reverse(data_.begin(), data_.end());
118           // 全部重新加载场景下,会回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID接口获取新的组件ID,
119           // 根据新的组件ID进行对比,ID不发生变化的进行复用,
120           // 针对新增ID的元素,调用NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件创建新的组件,
121           // 然后判断老数据中遗留的未使用ID,调用NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER删除老元素。
122           OH_ArkUI_NodeAdapter_ReloadAllItems(handle_);
123       }
124
125   private:
126       static void OnStaticAdapterEvent(ArkUI_NodeAdapterEvent *event) {
127           // 获取实例对象,回调实例事件。
128           auto itemAdapter = reinterpret_cast<ArkUIListItemAdapter *>(OH_ArkUI_NodeAdapterEvent_GetUserData(event));
129           itemAdapter->OnAdapterEvent(event);
130       }
131
132       void OnAdapterEvent(ArkUI_NodeAdapterEvent *event) {
133           auto type = OH_ArkUI_NodeAdapterEvent_GetType(event);
134           switch (type) {
135           case NODE_ADAPTER_EVENT_ON_GET_NODE_ID:
136               OnNewItemIdCreated(event);
137               break;
138           case NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER:
139               OnNewItemAttached(event);
140               break;
141           case NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER:
142               OnItemDetached(event);
143               break;
144           default:
145               break;
146           }
147       }
148
149       // 分配ID给需要显示的Item,用于ReloadAllItems场景的元素diff。
150       void OnNewItemIdCreated(ArkUI_NodeAdapterEvent *event) {
151           auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
152           static std::hash<std::string> hashId = std::hash<std::string>();
153           auto id = hashId(data_[index]);
154           OH_ArkUI_NodeAdapterEvent_SetNodeId(event, id);
155       }
156
157       // 需要新的Item显示在可见区域。
158       void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) {
159           auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
160           ArkUI_NodeHandle handle = nullptr;
161           if (!cachedItems_.empty()) {
162               // 使用并更新回收复用的缓存。
163               auto recycledItem = cachedItems_.top();
164               auto textItem = std::dynamic_pointer_cast<ArkUITextNode>(recycledItem->GetChildren().back());
165               textItem->SetTextContent(data_[index]);
166               handle = recycledItem->GetHandle();
167               // 释放缓存池的引用。
168               cachedItems_.pop();
169           } else {
170               // 创建新的元素。
171               auto listItem = std::make_shared<ArkUIListItemNode>();
172               auto textNode = std::make_shared<ArkUITextNode>();
173               textNode->SetTextContent(data_[index]);
174               textNode->SetFontSize(16);
175               textNode->SetPercentWidth(1);
176               textNode->SetHeight(100);
177               textNode->SetBackgroundColor(0xFFfffacd);
178               textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
179               listItem->AddChild(textNode);
180               auto swipeNode = std::make_shared<ArkUITextNode>();
181               swipeNode->RegisterOnClick([this, data = data_[index]](ArkUI_NodeEvent *event) {
182                   auto it = std::find(data_.begin(), data_.end(), data);
183                   if (it != data_.end()) {
184                       auto index = std::distance(data_.begin(), it);
185                       RemoveItem(index);
186                   }
187               });
188               listItem->SetSwiperAction(swipeNode);
189               handle = listItem->GetHandle();
190               // 保持文本列表项的引用。
191               items_.emplace(handle, listItem);
192           }
193           // 设置需要展示的元素。
194           OH_ArkUI_NodeAdapterEvent_SetItem(event, handle);
195       }
196
197       // Item从可见区域移除。
198       void OnItemDetached(ArkUI_NodeAdapterEvent *event) {
199           auto item = OH_ArkUI_NodeAdapterEvent_GetRemovedNode(event);
200           // 放置到缓存池中进行回收复用。
201           cachedItems_.emplace(items_[item]);
202       }
203
204
205       std::vector<std::string> data_;
206       ArkUI_NativeNodeAPI_1 *module_ = nullptr;
207       ArkUI_NodeAdapterHandle handle_ = nullptr;
208
209       // 管理NodeAdapter生成的元素。
210       std::unordered_map<ArkUI_NodeHandle, std::shared_ptr<ArkUIListItemNode>> items_;
211
212       // 管理回收复用组件池。
213       std::stack<std::shared_ptr<ArkUIListItemNode>> cachedItems_;
214   };
215
216   } // namespace NativeModule
217
218   #endif // MYAPPLICATION_ARKUILISTITEMADAPTER_H
219   ```
220
221### 在列表中应用懒加载适配器
222
2231. 在ArkUIListNode中添加SetLazyAdapter函数,给列表节点设置NODE_LIST_NODE_ADAPTER属性,并将NodeAdapter作为属性入参传入。
224   ```c++
225   // ArkUIListNode.h
226   // 列表封装对象。
227
228   #ifndef MYAPPLICATION_ARKUILISTNODE_H
229   #define MYAPPLICATION_ARKUILISTNODE_H
230
231   #include "ArkUIListItemAdapter.h"
232   #include "ArkUINode.h"
233
234   namespace NativeModule {
235   class ArkUIListNode : public ArkUINode {
236   public:
237       ArkUIListNode()
238           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {}
239
240       ~ArkUIListNode() override {
241           if (nativeModule_) {
242               nativeModule_->unregisterNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX);
243           }
244           if (adapter_) {
245               // 析构的时候卸载adapter下的UI组件。
246               nativeModule_->resetAttribute(handle_, NODE_LIST_NODE_ADAPTER);
247               adapter_.reset();
248           }
249       }
250
251       void SetScrollBarState(bool isShow) {
252           assert(handle_);
253           ArkUI_ScrollBarDisplayMode displayMode =
254               isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF;
255           ArkUI_NumberValue value[] = {{.i32 = displayMode}};
256           ArkUI_AttributeItem item = {value, 1};
257           nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item);
258       }
259
260       void RegisterOnScrollIndex(const std::function<void(int32_t index)> &onScrollIndex) {
261           assert(handle_);
262           onScrollIndex_ = onScrollIndex;
263           nativeModule_->registerNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX, 0, nullptr);
264       }
265       // 引入懒加载模块。
266       void SetLazyAdapter(const std::shared_ptr<ArkUIListItemAdapter> &adapter) {
267           assert(handle_);
268           ArkUI_AttributeItem item{nullptr, 0, nullptr, adapter->GetHandle()};
269           nativeModule_->setAttribute(handle_, NODE_LIST_NODE_ADAPTER, &item);
270           adapter_ = adapter;
271       }
272
273   protected:
274       void OnNodeEvent(ArkUI_NodeEvent *event) override {
275           auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
276           switch (eventType) {
277           case NODE_LIST_ON_SCROLL_INDEX: {
278               auto index = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event)->data[0];
279               if (onScrollIndex_) {
280                   onScrollIndex_(index.i32);
281               }
282           }
283           default: {
284           }
285           }
286       }
287
288   private:
289       std::function<void(int32_t index)> onScrollIndex_;
290
291       std::shared_ptr<ArkUIListItemAdapter> adapter_;
292   };
293   } // namespace NativeModule
294
295   #endif // MYAPPLICATION_ARKUILISTNODE_H
296   ```
297
2982. 创建List使用懒加载的示例代码,调用List节点的SetLazyAdapter接口设置懒加载适配器。
299   ```c++
300   // LazyTextListExample
301   // 懒加载列表示例代码。
302
303   #ifndef MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
304   #define MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
305
306   #include "ArkUIBaseNode.h"
307   #include "ArkUIListNode.h"
308
309
310   namespace NativeModule {
311
312   std::shared_ptr<ArkUIBaseNode> CreateLazyTextListExample(napi_env env) {
313       // 创建组件并挂载
314       // 1:创建List组件。
315       auto list = std::make_shared<ArkUIListNode>();
316       list->SetPercentWidth(1);
317       list->SetPercentHeight(1);
318       // 2:创建ListItem懒加载组件并挂载到List上。
319       auto adapter = std::make_shared<ArkUIListItemAdapter>();
320       list->SetLazyAdapter(adapter);
321       return list;
322   }
323   } // namespace NativeModule
324
325   #endif // MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
326   ```
327
3283. 在NativeEntry.cpp中调用List使用懒加载的示例代码。
329   ```c++
330   // NDK接口入口挂载文件。
331
332   #include "NativeEntry.h"
333
334   #include "LazyTextListExample.h"
335
336   #include <arkui/native_node_napi.h>
337   #include <arkui/native_type.h>
338   #include <js_native_api.h>
339   #include <uv.h>
340
341   namespace NativeModule {
342
343
344   napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
345       size_t argc = 1;
346       napi_value args[1] = {nullptr};
347
348       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
349
350       // 获取NodeContent
351       ArkUI_NodeContentHandle contentHandle;
352       OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
353       NativeEntry::GetInstance()->SetContentHandle(contentHandle);
354
355       // 创建懒加载文本列表
356       auto node = CreateLazyTextListExample(env);
357
358       // 保持Native侧对象到管理类中,维护生命周期。
359       NativeEntry::GetInstance()->SetRootNode(node);
360       return nullptr;
361   }
362
363   napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
364       // 从管理类中释放Native侧对象。
365       NativeEntry::GetInstance()->DisposeRootNode();
366       return nullptr;
367   }
368
369   } // namespace NativeModule
370   ```
371## 控制列表滚动位置
372
3731. 控制列表滚动到指定偏移量位置。
374    ```c++
375    //ArkUIListNode.h
376    //列表封装对象。
377    class ArkUIListNode: public ArkUINode {
378        //...
379        void ScrollTo(float offset) {
380            ArkUI_NumberValue value[] = {{.f32 =0},{.f32 = offset},{.f32 = 0}};
381            ArkUI_AttributeItem Item = {.value = value,.size = 3};
382            nativeModule_->setAttribute(handle_, NODE_SCROLL_OFFSET, &Item);
383        }
384    };
385    ```
3862. 控制列表滚动到指定元素。
387    ```c++
388    //ArkUIListNode.h
389    //列表封装对象。
390    class ArkUIListNode : public ArkUINode {
391        //...
392        void ScrollToIndex(int32_t index) {
393            ArkUI_NumberValue value[] = {{.i32 = index}};
394            ArkUI_AttributeItem Item = {.value = value, .size = 1};
395            nativeModule_->setAttribute(handle_, NODE_LIST_SCROLL_TO_INDEX, &Item);
396        }
397    };
398    ```
399
4003. 控制列表滚动指定偏移量。
401    ```c++
402   //ArkUIListNode.h
403    //列表封装对象。
404    class ArkUIListNode : public ArkUINode {
405        void ScrollBy(float offset) {
406            ArkUI_NumberValue value[] = {{.f32 =0},{.f32 = offset}};
407            ArkUI_AttributeItem Item = {.value = value, .size = 2};
408            nativeModule_->setAttribute(handle_, NODE_SCROLL_BY, &Item);
409        }
410    };
411    ```
412## ListItem横划删除
413
4141. ListItem设置NODE_LIST_ITEM_SWIPE_ACTION属性,将ArkUI_ListItemSwipeActionOption对象作为属性参数传入。
415    ```c++
416    // ArkUIListItemNode.h
417    //提供列表项的封装类。
418    #ifndef MYAPPLICATION_ARKUILISTITEMNODE_H
419    #define MYAPPLICATION_ARKUILISTITEMNODE_H
420    #include "ArkUINode.h"
421    namespace NativeModule{
422    class ArkUIListItemNode : public ArkUINode {
423    public:
424        ArkUIListItemNode()
425            : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM)) {}
426        ~ArkUIListItemNode() {
427            if(swipeAction_) {
428                OH_ArkUI_ListItemSwipeActionOption_Dispose(swipeAction_);
429            }
430            if (swipeItem_) {
431                OH_ArkUI_ListItemSwipeActionItem_Dispose(swipeItem_);
432            }
433        }
434        void SetSwiperAction(std::shared_ptr<ArkUINode> node) {
435            swipeContent_ = node;
436            swipeItem_ = OH_ArkUI_ListItemSwipeActionItem_Create();
437            OH_ArkUI_ListItemSwipeActionItem_SetContent(swipeItem_, node->GetHandle());
438            swipeAction_ = OH_ArkUI_ListItemSwipeActionOption_Create();
439            OH_ArkUI_ListItemSwipeActionOption_SetEnd(swipeAction_, swipeItem_);
440            ArkUI_AttributeItem Item = {.object= swipeAction_ };
441            nativeModule_->setAttribute(handle_,NODE_LIST_ITEM_SWIPE_ACTION, &Item);
442        }
443        std::shared_ptr<ArkUINode> GetSwipeContent() const {
444            return swipeContent_;
445        }
446        std::list<std::shared_ptr<ArkUIBaseNode>> &GetChildren() {
447            return children_;
448        }
449    private:
450        ArkUI_ListItemSwipeActionOption* swipeAction_ = nullptr;
451        ArkUI_ListItemSwipeActionItem* swipeItem_ = nullptr;
452        std::shared_ptr<ArkUINode> swipeContent_ = nullptr;
453        std::list<std::shared_ptr<ArkUIBaseNode>> children_;
454    };
455    }// namespace NativeModule
456    #endif// MYAPPLICATION_ARKUILISTITEMNODE_H
457    ```
458
4592. 创建ListItem时,创建ListItem的划出组件,并绑定点击事件,在点击事件中执行删除数据源操作。ListItem复用时,更新划出组件的绑定事件。
460    ```c++
461    // ArkUIListItemAdapter.h
462    class ArkUIListItemAdapter {
463        //...
464        //需要新的Item显示在可见区域。
465        void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) {
466            auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
467            ArkUI_NodeHandle handle = nullptr;
468            if (!cachedItems_.empty()) {
469                //使用并更新回收复用的缓存。
470                auto recycledItem = cachedItems_.top();
471                auto textItem = std::dynamic_pointer_cast<ArkUITextNode>(recycledItem->GetChildren().back());
472                textItem->SetTextContent(data_[index]);
473                handle = recycledItem->GetHandle();
474                auto swipeContent = recycledItem->GetSwipeContent();
475                swipeContent->RegisterOnClick([this, data = data_[index]]() {
476                    auto it = std::find(data_.begin(), data_.end(), data);
477                    if (it != data_.end()) {
478                        auto index = std::distance(data_.begin(), it);
479                        RemoveItem(index);
480                    }
481                });
482                //释放缓存池的引用。
483                cachedItems_.pop();
484            } else {
485                //创建新的元素。
486                auto listItem = std::make_shared<ArkUIListItemNode>();
487                auto textNode = std::make_shared<ArkUITextNode>();
488                textNode->SetTextContent(data_[index]);
489                textNode->SetFontSize(16);
490                textNode->SetPercentWidth(1);
491                textNode->SetHeight(100);
492                textNode->SetBackgroundColor(0xFFfffacd);
493                textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
494                listItem->AddChild(textNode);
495                //创建ListItem划出菜单。
496                auto swipeNode = std::make_shared<ArkUITextNode>();
497                swipeNode->SetTextContent("del");
498                swipeNode->SetFontSize(16);
499                swipeNode->SetFontColor(0xFFFFFFFF);
500                swipeNode->SetWidth(100);
501                swipeNode->SetHeight(100);
502                swipeNode->SetBackgroundColor(0xFFFF0000);
503                swipeNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
504                swipeNode->RegisterOnClick([this, data = data_[index]]() {
505                    auto it = std::find(data_.begin(), data_.end(), data);
506                    if (it != data_.end()) {
507                        auto index = std::distance(data_.begin(), it);
508                        RemoveItem(index);
509                    }
510                });
511                listItem->SetSwiperAction(swipeNode);
512                handle = listItem->GetHandle();
513                //保持文本列表项的引用。
514                items_.emplace(handle, listItem);
515            }
516            //设置需要展示的元素。
517            OH_ArkUI_NodeAdapterEvent_SetItem(event, handle);
518        }
519    }
520    ```
5213. ArkUIListItemAdapter中新增RemoveItem,用于删除数据源并且调用OH_ArkUI_NodeAdapter_RemoveItem接口通知框架刷新UI。
522    ```c++
523    // ArkUIListItemAdapter.h
524    class ArkUIListItemAdapter {
525        //...
526        void RemoveItem(size_t index) {
527            //删除第index个数据。
528            data_.erase(data_.begin() + index);
529            //如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件删除元素,
530            //根据是否有新增元素回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。
531            OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1);
532            //更新新的数量。
533            OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
534        }
535    };
536    ```
537## 使用分组列表
5381. 分组列表使用ListItemGroup组件实现,ListItemGroup支持添加header、footer设置函数,支持使用懒加载。
539    ```c++
540    // ArkUIListItemGroupNode.h
541
542    #ifndef MYAPPLICATION_ARKUILISTITEMGROUPNODE_H
543    #define MYAPPLICATION_ARKUILISTITEMGROUPNODE_H
544    #include "ArkUINode.h"
545    #include "ArkUIListItemAdapter.h"
546    namespace NativeModule{
547    class ArkUIListItemGroupNode : public ArkUINode {
548    public:
549        ArkUIListItemGroupNode()
550            : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM_GROUP)) {}
551        void SetHeader(std::shared_ptr<ArkUINode> node) {
552            if (node) {
553                ArkUI_AttributeItem Item = {.object = node->GetHandle()};
554                nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_HEADER, &Item);
555            } else {
556                nativeModule_->resetAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_HEADER);
557            }
558        }
559        void SetFooter(std::shared_ptr<ArkUINode> node) {
560            if (node) {
561                ArkUI_AttributeItem Item = {.object= node->GetHandle()};
562                nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_FOOTER, &Item);
563            } else {
564                nativeModule_->resetAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_FOOTER);
565            }
566        }
567        std::shared_ptr<ArkUINode> GetHeader() const {
568            return header_;
569        }
570        std::shared_ptr<ArkUINode> GetFooter() const {
571            return footer_;
572        }
573        //引入懒加载模块。
574        void SetLazyAdapter(const std::shared_ptr<ArkUIListItemAdapter> &adapter) {
575            assert(handle_);
576            ArkUI_AttributeItem item{nullptr,0, nullptr, adapter->GetHandle()};
577            nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_NODE_ADAPTER, &item);
578            adapter_ = adapter;
579        }
580    private:
581        std::shared_ptr<ArkUINode> header_;
582        std::shared_ptr<ArkUINode> footer_;
583        std::shared_ptr<ArkUIListItemAdapter> adapter_;
584    };
585    }// namespace NativeModule
586    #endif//MYAPPLICATION_ARKUILISTITEMGROUPNODE_H
587    ```
5882. List组件设置吸顶。
589    ```c++
590    // ArkUIListNode.h
591    //列表封装对象。
592    class ArkUIListNode : public ArkUINode{
593        //...
594        void SetSticky(ArkUI_StickyStyle style) {
595            assert(handle_);
596            ArkUI_NumberValue value[] = {{.i32 = style}};
597            ArkUI_AttributeItem item = {value, 1};
598            nativeModule_->setAttribute(handle_, NODE_LIST_STICKY, &item);
599        }
600    };
601    ```
6023. List组件下使用ListItemGroup实现分组列表界面。
603    ```c++
604    // LazyTextListExample.h
605    //懒加载列表示例代码。
606    #ifndef MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
607    #define MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
608    #include "ArkUIBaseNode.h"
609    #include "ArkUIListNode.h"
610    #include "ArkUIListItemGroupNode.h"
611    namespace NativeModule {
612    std::shared_ptr<ArkUIBaseNode> CreateLazyTextListExample() {
613    //创建组件并挂载
614    //1: 创建List组件。
615        auto list = std::make_shared<ArkUIListNode>();
616        list->SetPercentWidth(1);
617        list->SetPercentHeight(1);
618        //设置吸顶
619        list->SetSticky(ARKUI_STICKY_STYLE_BOTH);
620        //2: 创建ListItemGroup并挂载到List上。
621        for (int32_t i = 0; i < 3; i++) {
622            auto header = std::make_shared<ArkUITextNode>();
623            header->SetTextContent("header");
624            header->SetFontSize(16);
625            header->SetPercentWidth(1);
626            header->SetHeight(50);
627            header->SetBackgroundColor(0xFFDCDCDC);
628            header->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
629            auto listItemGroup = std::make_shared<ArkUIListItemGroupNode>();
630            listItemGroup->SetHeader(header);
631            auto adapter = std::make_shared<ArkUIListItemAdapter>();
632            listItemGroup->SetLazyAdapter(adapter);
633            list->AddChild(listItemGroup);
634        }
635        return list;
636    }
637    }// namespace NativeModule
638    #endif// MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
639    ```
640
641
642