1# 嵌入ArkTS组件
2
3
4ArkUI在Native侧提供的能力作为ArkTS的子集,部分能力不会在Native侧提供,如声明式UI语法,自定义struct组件,UI高级组件。
5
6
7针对需要使用ArkTS侧独立能力的场景,ArkUI开发框架提供了Native侧嵌入ArkTS组件的能力,该能力依赖[ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md)机制,通过ComponentContent完成对ArkTS组件的封装,然后将封装对象转递到Native侧,通过Native侧的[OH_ArkUI_GetNodeHandleFromNapiValue](../reference/apis-arkui/_ark_u_i___native_module.md#oh_arkui_getnodehandlefromnapivalue)接口转化为ArkUI_NodeHandle对象用于Native侧组件挂载使用。
8
9
10> **说明:**
11>
12> - 通过OH_ArkUI_GetNodeHandleFromNapiValue接口获得的ArkUI_NodeHandle对象只能作为子组件参数使用,如[addChild](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addchild)接口的第二个参数,将该对象使用在其他场景下,如[setAttribute](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#setattribute)设置属性将不生效并返回错误码。
13>
14> - 针对Native侧修改ArkTS组件的场景,需要在Native侧通过Node-API方式构建ArkTS侧的更新数据,再通过ComponentContent的[update](../reference/apis-arkui/js-apis-arkui-ComponentContent.md#update)接口更新。
15>
16> - [构建自定义组件](ndk-build-custom-components.md)时,相关函数如measureNode等无法对ArkTS模块内部的组件进行调用。
17
18
19以下示例代码在[接入ArkTS页面](ndk-access-the-arkts-page.md)章节基础上引入ArkTS的Refresh组件。
20
21
22**图1** Refresh组件挂载文本列表
23
24![refresh_text_list](figures/refresh_text_list.gif)
25
26
271. 注册ArkTS组件创建函数给Native侧,以便Native侧调用,创建函数使用ComponentContent能力进行封装。
28   ```ts
29   // MixedModule.ets
30   // 使用ComponentContent能力创建ArkTS组件
31
32   import { NodeContent,  UIContext, RefreshModifier, ComponentContent } from '@kit.ArkUI';
33
34   // 定义Native侧和ArkTS进行交互的数据对象。
35   interface NativeRefreshAttribute {
36     isRefreshing: boolean;
37     width?: number;
38     height?: number;
39     backgroundColor?: number;
40     refreshOffset?: number;
41     pullToRefresh?: boolean
42     onRefreshing?: () => void;
43     onOffsetChange?: (offset: number) => void;
44   }
45
46   // 定义@Builder函数的入参格式。
47   interface RefreshAttribute {
48     isRefreshing: boolean;
49     // 属性设置通过Modifier优化性能
50     modifier?: RefreshModifier;
51     slot?: NodeContent;
52     onRefreshing?: () => void;
53     onOffsetChange?: (offset: number) => void;
54   }
55
56   // ComponentContent封装ArkTS组件依赖全局@Builder函数,涉及复杂自定义组件场景,可以在@Builder函数中嵌套@Component自定义组件。
57   // @Builder函数提供入参方式,方便后续通过ComponentContent的update接口进行参数更新。
58   @Builder
59   function mixedRefresh(attribute: RefreshAttribute) {
60     Refresh({ refreshing: attribute.isRefreshing }) {
61       // Refresh作为容器组件,需要使用ContentSlot机制预留子组件占位
62       ContentSlot(attribute.slot)
63     }.attributeModifier(attribute.modifier)
64     .onRefreshing(() => {
65       console.info("on onRefreshing");
66       if (attribute.onRefreshing) {
67         console.info("on native onRefreshing");
68         attribute.onRefreshing();
69       }
70     })
71     .onOffsetChange((value: number) => {
72       console.info("on offset change: " + value);
73       if (attribute.onOffsetChange) {
74         console.info("on native onOffsetChange");
75         attribute.onOffsetChange(value);
76       }
77     })
78   }
79
80   // 定义创建函数的返回值,用于ArkTS侧和Native侧的交互。
81   interface MixedModuleResult {
82     // 定义针对Refresh构建函数的封装对象,用于Native侧转化为ArkUI_NodeHandle对象。
83     content?: ComponentContent<RefreshAttribute>;
84     // Refresh作为容器组件,需要使用ContentSlot机制挂载Native侧的子组件。
85     childSlot?: NodeContent;
86   }
87
88   // 提供创建ArkTS组件的入口函数。
89   export function createMixedRefresh(value: NativeRefreshAttribute): MixedModuleResult {
90     console.info("createMixedRefresh");
91     // 通过AppStorage对象在Ability启动的时候保持UI上下文对象。
92     let uiContent = AppStorage.get<UIContext>("context");
93     let modifier = new RefreshModifier();
94     if (value.width) {
95       modifier.width(value.width)
96     }
97     if (value.height) {
98       modifier.height(value.height)
99     }
100     if (value.backgroundColor) {
101       modifier.backgroundColor(value.backgroundColor)
102     }
103     if (value.pullToRefresh) {
104       modifier.pullToRefresh(value.pullToRefresh)
105     }
106     if (value.refreshOffset) {
107       modifier.refreshOffset(value.refreshOffset)
108     }
109     // 创建NodeContent插槽对象用于Refresh子组件挂载。
110     let nodeSlot = new NodeContent();
111     // 通过ComponentContent创建Refresh组件并将它封装起来。
112     let content = new ComponentContent<RefreshAttribute>(uiContent!, wrapBuilder<[RefreshAttribute]>(mixedRefresh),
113       {
114         isRefreshing: value.isRefreshing,
115         modifier: modifier,
116         slot: nodeSlot,
117         onRefreshing: value.onRefreshing,
118         onOffsetChange: value.onOffsetChange
119       });
120     // 将Refresh组件的封装对象及其子组件插槽对象传递给Native侧。
121     return { content: content, childSlot: nodeSlot };
122   }
123
124   // 定义Refresh组件的更新函数,用于Native侧更新。
125   // 在更新场景下,需要将Refresh组件的封装对象及其子组件插槽对象返回,防止组件重新创建。
126   export function updateMixedRefresh(refresh: ComponentContent<RefreshAttribute>, childSlot: NodeContent,
127     value: NativeRefreshAttribute): void {
128     let modifier = new RefreshModifier();
129     if (value.width) {
130       modifier.width(value.width)
131     }
132     if (value.height) {
133       modifier.height(value.height)
134     }
135     if (value.backgroundColor) {
136       modifier.backgroundColor(value.backgroundColor)
137     }
138     if (value.pullToRefresh) {
139       modifier.pullToRefresh(value.pullToRefresh)
140     }
141     if (value.refreshOffset) {
142       modifier.refreshOffset(value.refreshOffset)
143     }
144     // 调用ComponentContent的update接口进行更新。
145     refresh.update({
146       isRefreshing: value.isRefreshing,
147       modifier: modifier,
148       slot: childSlot,
149       onRefreshing: value.onRefreshing,
150       onOffsetChange: value.onOffsetChange
151     })
152   }
153
154   ```
155
1562. 将创建和更新函数注册给Native侧。
157   ```ts
158   // entry.ets
159   import nativeNode from 'libentry.so';
160   import { NodeContent } from '@kit.ArkUI';
161   import { createMixedRefresh, updateMixedRefresh } from './MixedModule'
162
163   @Entry
164   @Component
165   struct Index {
166     private rootSlot = new NodeContent();
167     @State @Watch('changeNativeFlag') showNative: boolean = false;
168
169     aboutToAppear(): void {
170       // 设置uiContext;
171       AppStorage.setOrCreate<UIContext>("context", this.getUIContext());
172       // 设置混合模式下的builder函数。
173       nativeNode.registerCreateMixedRefreshNode(createMixedRefresh);
174       nativeNode.registerUpdateMixedRefreshNode(updateMixedRefresh);
175     }
176
177     changeNativeFlag(): void {
178       if (this.showNative) {
179         // 创建NativeModule组件挂载
180         nativeNode.createNativeRoot(this.rootSlot)
181       } else {
182         // 销毁NativeModule组件
183         nativeNode.destroyNativeRoot()
184       }
185     }
186
187     build() {
188       Column() {
189         Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => {
190           this.showNative = !this.showNative
191         })
192         Row() {
193           // ArkTS插入Native组件。
194           ContentSlot(this.rootSlot)
195         }.layoutWeight(1)
196       }
197       .width('100%')
198       .height('100%')
199     }
200   }
201   ```
202
203   ```cpp
204   // native_init.cpp
205   #include "napi/native_api.h"
206   #include "ArkUIMixedRefresh.h"
207   #include "NativeEntry.h"
208
209   EXTERN_C_START
210   static napi_value Init(napi_env env, napi_value exports) {
211       napi_property_descriptor desc[] = {
212           {"createNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr},
213           // 注册混合模式创建方法。
214           {"registerCreateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterCreateRefresh, nullptr,
215            nullptr, nullptr, napi_default, nullptr},
216           // 注册混合模式更新方法。
217           {"registerUpdateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterUpdateRefresh, nullptr,
218            nullptr, nullptr, napi_default, nullptr},
219           {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default,
220            nullptr}};
221       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
222       return exports;
223   }
224   EXTERN_C_END
225
226   static napi_module demoModule = {
227       .nm_version = 1,
228       .nm_flags = 0,
229       .nm_filename = nullptr,
230       .nm_register_func = Init,
231       .nm_modname = "entry",
232       .nm_priv = ((void *)0),
233       .reserved = {0},
234   };
235
236   extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
237   ```
238
2393. Native侧通过Node-API保存创建和更新函数,用于后续调用。
240   ```c
241   // ArkUIMixedRefresh.h
242   // 混合模式交互类。
243
244   #ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H
245   #define MYAPPLICATION_ARKUIMIXEDREFRESH_H
246
247   #include "ArkUIMixedNode.h"
248
249   #include <optional>
250
251   #include <arkui/native_node_napi.h>
252   #include <js_native_api_types.h>
253
254   namespace NativeModule {
255
256   class ArkUIMixedRefresh : public ArkUIMixedNode {
257   public:
258       static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info);
259       static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info);
260   };
261
262   } // namespace NativeModule
263
264   #endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H
265   ```
266
267   ```cpp
268   // ArkUIMixedRefresh.cpp
269   // 混合模式交互类。
270
271   #include "ArkUIMixedRefresh.h"
272   #include <hilog/log.h>
273
274   namespace NativeModule {
275   namespace {
276   napi_env g_env;
277   napi_ref g_createRefresh;
278   napi_ref g_updateRefresh;
279   } // namespace
280
281   napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) {
282       size_t argc = 1;
283       napi_value args[1] = {nullptr};
284
285       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
286
287       g_env = env;
288       napi_ref refer;
289       // 创建引用之后保存,防止释放。
290       napi_create_reference(env, args[0], 1, &refer);
291
292       g_createRefresh = refer;
293       return nullptr;
294   }
295
296   napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) {
297       size_t argc = 1;
298       napi_value args[1] = {nullptr};
299
300       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
301
302       g_env = env;
303       napi_ref refer;
304       // 创建引用之后保存,防止释放。
305       napi_create_reference(env, args[0], 1, &refer);
306
307       g_updateRefresh = refer;
308       return nullptr;
309   }
310
311   } // namespace NativeModule
312   ```
313
3144. 抽象混合模式下组件的基类,用于通用逻辑管理。
315   ```c
316   // ArkUIMixedNode.h
317   // 混合模式基类。
318
319   #ifndef MYAPPLICATION_ARKUIMIXEDNODE_H
320   #define MYAPPLICATION_ARKUIMIXEDNODE_H
321
322   #include <js_native_api.h>
323   #include <js_native_api_types.h>
324
325   #include "ArkUIBaseNode.h"
326   #include "NativeModule.h"
327
328   namespace NativeModule {
329
330   // Wrap ArkTS Node
331   class ArkUIMixedNode : public ArkUIBaseNode {
332   public:
333       ArkUIMixedNode(ArkUI_NodeHandle handle, napi_env env, napi_ref componentContent)
334           : ArkUIBaseNode(handle), env_(env), componentContent_(componentContent) {}
335
336       // 在基类析构的时候需要把混合模式在ArkTS侧的对象释放掉。
337       ~ArkUIMixedNode() override { napi_delete_reference(env_, componentContent_); }
338
339   protected:
340       napi_env env_;
341       napi_ref componentContent_;
342   };
343
344   } // namespace NativeModule
345
346   #endif // MYAPPLICATION_ARKUIMIXEDNODE_H
347   ```
348
3495. 实现Refresh组件的混合模式封装对象。
350   ```c
351   // ArkUIMixedRefresh.h
352   // Refresh混合模式在Native侧的封装对象。
353
354   #ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H
355   #define MYAPPLICATION_ARKUIMIXEDREFRESH_H
356
357   #include "ArkUIMixedNode.h"
358   #include "ArkUIBaseNode.h"
359
360   #include <optional>
361
362   #include <arkui/native_node_napi.h>
363   #include <js_native_api_types.h>
364
365   namespace NativeModule {
366
367   // 定义Native侧和ArkTS侧的交互数据结构。
368   struct NativeRefreshAttribute {
369       std::optional<bool> isRefreshing;
370       std::optional<float> width;
371       std::optional<float> height;
372       std::optional<uint32_t> backgroundColor;
373       std::optional<float> refreshOffset;
374       std::optional<bool> pullToRefresh;
375       std::function<void()> onRefreshing;
376       std::function<void(float)> onOffsetChange;
377   };
378
379   class ArkUIMixedRefresh : public ArkUIMixedNode {
380   public:
381       // 调用ArkTS的方法创建Refresh组件。
382       static const std::shared_ptr<ArkUIMixedRefresh> Create(const NativeRefreshAttribute &attribute);
383
384       ArkUIMixedRefresh(ArkUI_NodeHandle handle, ArkUI_NodeContentHandle contentHandle, napi_env env,
385                         napi_ref componentContent, napi_ref nodeContent)
386           : ArkUIMixedNode(handle, env, componentContent), contentHandle_(contentHandle), nodeContent_(nodeContent) {}
387
388       ArkUIMixedRefresh() : ArkUIMixedNode(nullptr, nullptr, nullptr) {}
389
390       ~ArkUIMixedRefresh() override { napi_delete_reference(env_, nodeContent_); } // 释放子节点占位组件插槽对象。
391
392       void SetWidth(float width) { attribute_.width = width; }
393
394       void SetHeight(float height) { attribute_.height = height; }
395
396       void SetBackgroundColor(uint32_t color) { attribute_.backgroundColor = color; }
397
398       void SetRefreshState(bool isRefreshing) { attribute_.isRefreshing = isRefreshing; }
399
400       void SetPullToRefresh(bool pullToRefresh) { attribute_.pullToRefresh = pullToRefresh; }
401
402       void SetRefreshOffset(float offset) { attribute_.refreshOffset = offset; }
403
404       void SetRefreshCallback(const std::function<void()> &callback) { attribute_.onRefreshing = callback; }
405
406       void SetOnOffsetChange(const std::function<void(float)> &callback) { attribute_.onOffsetChange = callback; }
407
408       // 避免频繁跨语言,在Native侧缓存属性事件,批量通知。
409       void FlushMixedModeCmd();
410
411       static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info);
412       static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info);
413
414   protected:
415       void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
416           assert(contentHandle_);
417           // 使用NodeContent挂载组件(可以使用ArkTS在Native侧通过ComponentContent的转化对象,也可以是纯Native组件)到ArkTS组件下面。
418           OH_ArkUI_NodeContent_AddNode(contentHandle_, child->GetHandle());
419       }
420
421       void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
422           assert(contentHandle_);
423           // 使用NodeContent卸载组件。
424           OH_ArkUI_NodeContent_RemoveNode(contentHandle_, child->GetHandle());
425       }
426
427       void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override {
428           assert(contentHandle_);
429           // 使用NodeContent插入组件。
430           OH_ArkUI_NodeContent_InsertNode(contentHandle_, child->GetHandle(), index);
431       }
432
433   private:
434       // 使用napi接口创建ArkTS侧的数据结构。
435       static napi_value CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData);
436
437       ArkUI_NodeContentHandle contentHandle_;
438       napi_ref nodeContent_;
439       NativeRefreshAttribute attribute_;
440   };
441
442   } // namespace NativeModule
443
444   #endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H
445   ```
446
447   相关实现类说明:
448
449   ```c
450   #include "ArkUIMixedRefresh.h"
451   #include <hilog/log.h>
452
453   namespace NativeModule {
454   namespace {
455   napi_env g_env;
456   napi_ref g_createRefresh;
457   napi_ref g_updateRefresh;
458   } // namespace
459
460   // 使用Napi接口创建与ArkTS侧交互的数据结构,用于Refresh组件的创建和更新。
461   napi_value ArkUIMixedRefresh::CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData) {
462       napi_property_descriptor desc[] = {
463           {"width", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
464           {"height", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
465           {"backgroundColor", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
466           {"pullToRefresh", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
467           {"isRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
468           {"refreshOffset", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
469           {"onRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
470           {"onOffsetChange", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
471       };
472       if (attribute.width) {
473           napi_value width;
474           napi_create_double(g_env, attribute.width.value(), &width);
475           desc[0].value = width;
476       }
477       if (attribute.height) {
478           napi_value height;
479           napi_create_double(g_env, attribute.height.value(), &height);
480           desc[1].value = height;
481       }
482       if (attribute.backgroundColor) {
483           napi_value backgroundColor;
484           napi_create_uint32(g_env, attribute.backgroundColor.value(), &backgroundColor);
485           desc[2].value = backgroundColor;
486       }
487       if (attribute.pullToRefresh) {
488           napi_value pullToRefresh;
489           napi_create_int32(g_env, attribute.pullToRefresh.value(), &pullToRefresh);
490           desc[3].value = pullToRefresh;
491       }
492       if (attribute.isRefreshing) {
493           napi_value isRefreshing;
494           napi_create_int32(g_env, attribute.isRefreshing.value(), &isRefreshing);
495           desc[4].value = isRefreshing;
496       }
497       if (attribute.refreshOffset) {
498           napi_value refreshOffset;
499           napi_create_double(g_env, attribute.refreshOffset.value(), &refreshOffset);
500           desc[5].value = refreshOffset;
501       }
502       if (attribute.onRefreshing) {
503           OH_LOG_INFO(LOG_APP, "onRefreshing start");
504           desc[6].method = [](napi_env env, napi_callback_info info) -> napi_value {
505               OH_LOG_INFO(LOG_APP, "onRefreshing callback");
506               size_t argc = 0;
507               napi_value args[0];
508               void *data;
509               napi_get_cb_info(env, info, &argc, args, nullptr, &data);
510               auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(data);
511               if (refresh && refresh->attribute_.onRefreshing) {
512                   refresh->attribute_.onRefreshing();
513               }
514               return nullptr;
515           };
516       }
517       if (attribute.onOffsetChange) {
518           OH_LOG_INFO(LOG_APP, "onOffsetChange start");
519           desc[7].method = [](napi_env env, napi_callback_info info) -> napi_value {
520               OH_LOG_INFO(LOG_APP, "onOffsetChange callback");
521               size_t argc = 1;
522               napi_value args[1] = {nullptr};
523               void *data;
524               napi_get_cb_info(env, info, &argc, args, nullptr, &data);
525               double offset = 0.0;
526               napi_get_value_double(env, args[0], &offset);
527               auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(data);
528               if (refresh && refresh->attribute_.onOffsetChange) {
529                   refresh->attribute_.onOffsetChange(offset);
530               }
531               return nullptr;
532           };
533       }
534       napi_value refreshAttribute = nullptr;
535       auto result = napi_create_object_with_properties(g_env, &refreshAttribute, sizeof(desc) / sizeof(desc[0]), desc);
536       if (result != napi_ok) {
537           return nullptr;
538       }
539       return refreshAttribute;
540   }
541
542   // 创建ArkTS侧的组件并保存在Native侧的封装对象中。
543   const std::shared_ptr<ArkUIMixedRefresh> ArkUIMixedRefresh::Create(const NativeRefreshAttribute &attribute) {
544       napi_handle_scope scope;
545       napi_open_handle_scope(g_env, &scope);
546       auto refresh = std::make_shared<ArkUIMixedRefresh>();
547       auto refreshAttribute = CreateRefreshAttribute(attribute, refresh.get());
548       if (refreshAttribute == nullptr) {
549           napi_close_handle_scope(g_env, scope);
550           return nullptr;
551       }
552       napi_value result = nullptr;
553       napi_value argv[1] = {refreshAttribute};
554       napi_value createRefresh = nullptr;
555       napi_get_reference_value(g_env, g_createRefresh, &createRefresh);
556       // 调用ArkTS的Create函数创建ArkTS的ComponentContent。
557       napi_call_function(g_env, nullptr, createRefresh, 1, argv, &result);
558
559       // 获取ArkTS的Refresh组件。
560       napi_value componentContent = nullptr;
561       napi_get_named_property(g_env, result, "content", &componentContent);
562       ArkUI_NodeHandle handle;
563       OH_ArkUI_GetNodeHandleFromNapiValue(g_env, componentContent, &handle);
564       assert(handle);
565       // 获取ArkTS的Refresh组件的子组件插槽。
566       napi_value nodeContent = nullptr;
567       napi_get_named_property(g_env, result, "childSlot", &nodeContent);
568       ArkUI_NodeContentHandle contentHandle;
569       OH_ArkUI_GetNodeContentFromNapiValue(g_env, nodeContent, &contentHandle);
570       assert(contentHandle);
571       // 保存ArkTS的ComponentContent用于防止ArkTS侧对象释放以及后续的更新。
572       napi_ref componentContentRef;
573       napi_create_reference(g_env, componentContent, 1, &componentContentRef);
574       // 保存ArkTS的NodeContent用于防止ArkTS侧对象释放以及后续的更新。
575       napi_ref nodeContentRef;
576       napi_create_reference(g_env, nodeContent, 1, &nodeContentRef);
577       // 更新Refresh组件相关参数。
578       refresh->handle_ = handle;
579       refresh->env_ = g_env;
580       refresh->componentContent_ = componentContentRef;
581       refresh->nodeContent_ = nodeContentRef;
582       refresh->contentHandle_ = contentHandle;
583       refresh->attribute_ = attribute;
584       return refresh;
585   }
586   // 更新函数实现。
587   void ArkUIMixedRefresh::FlushMixedModeCmd() {
588       napi_handle_scope scope;
589       napi_open_handle_scope(g_env, &scope);
590       // 创建调用ArkTS接口入参。
591       auto refreshAttribute = CreateRefreshAttribute(attribute_, this);
592       if (refreshAttribute == nullptr) {
593           napi_close_handle_scope(g_env, scope);
594           return;
595       }
596       // 获取更新接口的剩余两个接口参数。
597       napi_value componentContent = nullptr;
598       napi_get_reference_value(g_env, componentContent_, &componentContent);
599       napi_value nodeContent = nullptr;
600       napi_get_reference_value(g_env, nodeContent_, &nodeContent);
601
602       napi_value argv[3] = {componentContent, nodeContent, refreshAttribute};
603       napi_value updateRefresh = nullptr;
604       napi_get_reference_value(g_env, g_updateRefresh, &updateRefresh);
605       // 调用ArkTS的Update函数进行更新。
606       napi_value result = nullptr;
607       napi_call_function(g_env, nullptr, updateRefresh, 3, argv, &result);
608   }
609
610   napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) {
611       size_t argc = 1;
612       napi_value args[1] = {nullptr};
613
614       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
615
616       g_env = env;
617       napi_ref refer;
618       napi_create_reference(env, args[0], 1, &refer);
619
620       g_createRefresh = refer;
621       return nullptr;
622   }
623
624   napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) {
625       size_t argc = 1;
626       napi_value args[1] = {nullptr};
627
628       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
629
630       g_env = env;
631       napi_ref refer;
632       napi_create_reference(env, args[0], 1, &refer);
633
634       g_updateRefresh = refer;
635       return nullptr;
636   }
637
638   } // namespace NativeModule
639
640   ```
641
6426. 使用[接入ArkTS页面](ndk-access-the-arkts-page.md)章节的页面结构,并沿用[定时器模块相关简单实现](ndk-loading-long-list.md),将Refresh组件作为文本列表的父组件。
643   ```c
644   // MixedRefreshExample.h
645   // 混合模式示例代码。
646
647   #ifndef MYAPPLICATION_MIXEDREFRESHEXAMPLE_H
648   #define MYAPPLICATION_MIXEDREFRESHEXAMPLE_H
649
650   #include "ArkUIBaseNode.h"
651   #include "ArkUIMixedRefresh.h"
652   #include "TextListExample.h"
653   #include "UITimer.h"
654
655   #include <js_native_api_types.h>
656
657   namespace NativeModule {
658
659   std::shared_ptr<ArkUIBaseNode> CreateMixedRefreshList(napi_env env) {
660       auto list = CreateTextListExample();
661       // 混合模式创建Refresh组件并挂载List组件。
662       NativeRefreshAttribute nativeRefreshAttribute{
663           .backgroundColor = 0xFF89CFF0, .refreshOffset = 64, .pullToRefresh = true};
664       auto refresh = ArkUIMixedRefresh::Create(nativeRefreshAttribute);
665       refresh->AddChild(list);
666
667       // 设置混合模式下的事件。
668       refresh->SetOnOffsetChange(
669           [](float offset) { OH_LOG_INFO(LOG_APP, "on refresh offset changed: %{public}f", offset); });
670       refresh->SetRefreshCallback([refreshPtr = refresh.get(), env]() {
671           OH_LOG_INFO(LOG_APP, "on refreshing");
672           // 启动定时器,模拟数据获取。
673           CreateNativeTimer(env, refreshPtr, 1, [](void *userData, int32_t count) {
674               // 数据获取后关闭刷新。
675               auto refresh = reinterpret_cast<ArkUIMixedRefresh *>(userData);
676               refresh->SetRefreshState(false);
677               refresh->FlushMixedModeCmd();
678           });
679       });
680
681       // 更新事件到ArkTS侧。
682       refresh->FlushMixedModeCmd();
683       return refresh;
684   }
685
686   } // namespace NativeModule
687
688   #endif // MYAPPLICATION_MIXEDREFRESHEXAMPLE_H
689   ```
690
691   替换入口组件创建为下拉刷新文本列表。
692
693   ```c
694   #include "NativeEntry.h"
695
696   #include "ArkUIMixedRefresh.h"
697   #include "MixedRefreshExample.h"
698   #include "TextListExample.h"
699
700   #include <arkui/native_node_napi.h>
701   #include <arkui/native_type.h>
702   #include <js_native_api.h>
703   #include <uv.h>
704
705   namespace NativeModule {
706
707   napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
708       size_t argc = 1;
709       napi_value args[1] = {nullptr};
710
711       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
712
713       // 获取NodeContent
714       ArkUI_NodeContentHandle contentHandle;
715       OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
716       NativeEntry::GetInstance()->SetContentHandle(contentHandle);
717
718       // 创建Refresh文本列表
719       auto refresh = CreateMixedRefreshList(env);
720
721       // 保持Native侧对象到管理类中,维护生命周期。
722       NativeEntry::GetInstance()->SetRootNode(refresh);
723       return nullptr;
724   }
725
726   napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
727       // 从管理类中释放Native侧对象。
728       NativeEntry::GetInstance()->DisposeRootNode();
729       return nullptr;
730   }
731
732   } // namespace NativeModule
733
734   ```
735
736