针对List、Grid、WaterFlow、Swiper组件,提供NodeAdapter对象替代ArkTS侧的LazyForEach功能,用于按需生成子组件,其中List组件的属性枚举值为NODE_LIST_NODE_ADAPTER,Grid组件的属性枚举值为NODE_GRID_NODE_ADAPTER,WaterFlow组件的属性枚举值为NODE_WATER_FLOW_NODE_ADAPTER,Swiper组件的属性枚举值为NODE_SWIPER_NODE_ADAPTER。
虽然都用于按需生成组件,但不同于ArkTS的LazyForEach,NodeAdapter对象的规格如下:
-
设置了NodeAdapter属性的节点,不再支持addChild等直接添加子组件的接口。子组件完全由NodeAdapter管理,使用属性方法设置NodeAdapter时,会判断父组件是否已经存在子节点,如果父组件已经存在子节点,则设置NodeAdapter操作失败,返回错误码。
-
NodeApdater通过相关事件通知开发者按需生成组件,类似组件事件机制,开发者使用NodeAdapter时要注册事件监听器,在监听器事件中处理逻辑,相关事件通过ArkUI_NodeAdapterEventType定义。另外NodeAdapter不会主动释放不在屏幕内显示的组件对象,开发者需要在NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件中进行组件对象的释放,或者进行缓存复用。下图展示了典型列表滑动场景下的事件触发机制:
以下示例代码针对接入ArkTS页面章节代码进行优化,引入懒加载机制实现文本列表:
-
接入ArkTS,参考接入ArkTS页面。
-
懒加载适配器相关功能实现。
// ArkUIListItemAdapter // 用于文本列表懒加载功能代码。 #ifndef MYAPPLICATION_ARKUILISTITEMADAPTER_H #define MYAPPLICATION_ARKUILISTITEMADAPTER_H #include <arkui/native_node.h> #include <stack> #include <string> #include <unordered_set> #include "ArkUIListItemNode.h" #include "ArkUITextNode.h" #include "nativeModule.h" namespace NativeModule { class ArkUIListItemAdapter { public: ArkUIListItemAdapter() : module_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()), handle_(OH_ArkUI_NodeAdapter_Create()) { // 使用NodeAdapter创建函数。 // 初始化懒加载数据。 for (int32_t i = 0; i < 1000; i++) { data_.emplace_back(std::to_string(i)); } // 设置懒加载数据。 OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); // 设置懒加载回调事件。 OH_ArkUI_NodeAdapter_RegisterEventReceiver(handle_, this, OnStaticAdapterEvent); } ~ArkUIListItemAdapter() { // 释放创建的组件。 while (!cachedItems_.empty()) { cachedItems_.pop(); } items_.clear(); // 释放Adapter相关资源。 OH_ArkUI_NodeAdapter_UnregisterEventReceiver(handle_); OH_ArkUI_NodeAdapter_Dispose(handle_); } ArkUI_NodeAdapterHandle GetHandle() const { return handle_; } void RemoveItem(int32_t index) { // 删除第index个数据。 data_.erase(data_.begin() + index); // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件删除元素, // 根据是否有新增元素回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。 OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1); // 更新新的数量。 OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); } void InsertItem(int32_t index, const std::string &value) { data_.insert(data_.begin() + index, value); // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件, // 根据是否有删除元素回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件。 OH_ArkUI_NodeAdapter_InsertItem(handle_, index, 1); // 更新新的数量。 OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size()); } void MoveItem(int32_t oldIndex, int32_t newIndex) { auto temp = data_[oldIndex];