首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

HarmonyOS Next开发学习手册——使用NDK接口构建UI(嵌入ArkTS组件)

  • 25-02-22 07:01
  • 3880
  • 11126
blog.csdn.net

ArkUI在Native侧提供的能力作为ArkTS的子集,部分能力不会在Native侧提供,如声明式UI语法,自定义struct组件,UI高级组件。

针对需要使用ArkTS侧独立能力的场景,ArkUI开发框架提供了Native侧嵌入ArkTS组件的能力,该能力依赖 ComponentContent 机制,通过ComponentContent完成对ArkTS组件的封装,然后将封装对象转递到Native侧,通过Native侧的 OH_ArkUI_GetNodeHandleFromNapiValue 接口转化为ArkUI_NodeHandle对象用于Native侧组件挂载使用。

说明

  • 通过OH_ArkUI_GetNodeHandleFromNapiValue接口获得的ArkUI_NodeHandle对象只能作为子组件参数使用,如 addChild 接口的第二个参数,将该对象使用在其他场景下,如 setAttribute 设置属性将不生效并返回错误码。

  • 针对Native侧修改ArkTS组件的场景,需要在Native侧通过Node-API方式构建ArkTS侧的更新数据,再通过ConmponnetContent的 update 接口更新。

  • 自定义场景 下,相关函数如measureNode等无法对ArkTS模块内部的组件进行调用。

以下示例代码在 接入ArkTS页面 章节基础上引入ArkTS的Refresh组件。

图1 Refresh组件挂载文本列表

  1. 注册ArkTS组件创建函数给Native侧,以便Native侧调用,创建函数使用ComponentContent能力进行封装。
// MixedModule.ets
// 使用ComponentContent能力创建ArkTS组件

import { NodeContent } from '@ohos.arkui.node'
import { UIContext } from '@ohos.arkui.UIContext';
import { RefreshModifier } from '@ohos.arkui.modifier';
import { ComponentContent } from '@ohos.arkui.node'

// 定义Native侧和ArkTS进行交互的数据对象。
interface NativeRefreshAttribute {
  isRefreshing: boolean;
  width?: number;
  height?: number;
  backgroundColor?: number;
  refreshOffset?: number;
  pullToRefresh?: boolean
  onRefreshing?: () => void;
  onOffsetChange?: (offset: number) => void;
}

// 定义@Builder函数的入参格式。
interface RefreshAttribute {
  isRefreshing: boolean;
  // 属性设置通过Modifier优化性能
  modifier?: RefreshModifier;
  slot?: NodeContent;
  onRefreshing?: () => void;
  onOffsetChange?: (offset: number) => void;
}

// ComponnetContent封装ArkTS组件依赖全局@Builder函数,涉及复杂自定义组件场景,可以在@Builder函数中嵌套@Component自定义组件。
// @Builder函数提供入参方式,方便后续通过ComponentContent的update接口进行参数更新。
@Builder
function mixedRefresh(attribute: RefreshAttribute) {
  Refresh({ refreshing: attribute.isRefreshing }) {
    // Refresh作为容器组件,需要使用ContentSlot机制预留子组件占位
    ContentSlot(attribute.slot)
  }.attributeModifier(attribute.modifier)
  .onRefreshing(() => {
    console.info("on onRefreshing");
    if (attribute.onRefreshing) {
      console.info("on native onRefreshing");
      attribute.onRefreshing();
    }
  })
  .onOffsetChange((value: number) => {
    console.info("on offset change: " + value);
    if (attribute.onOffsetChange) {
      console.info("on native onOffsetChange");
      attribute.onOffsetChange(value);
    }
  })
}

// 定义创建函数的返回值,用于ArkTS侧和Native侧的交互。
interface MixedModuleResult {
  // 定义针对Refresh构建函数的封装对象,用于Native侧转化为ArkUI_NodeHandle对象。
  content?: ComponentContent;
  // Refresh作为容器组件,需要使用ContentSlot机制挂载Native侧的子组件。
  childSlot?: NodeContent;
}

// 提供创建ArkTS组件的入口函数。
export function createMixedRefresh(value: NativeRefreshAttribute): MixedModuleResult {
  console.info("createMixedRefresh");
  // 通过AppStorage对象在Ability启动的时候保持UI上下文对象。
  let uiContent = AppStorage.get("context");
  let modifier = new RefreshModifier();
  if (value.width) {
    modifier.width(value.width)
  }
  if (value.height) {
    modifier.height(value.height)
  }
  if (value.backgroundColor) {
    modifier.backgroundColor(value.backgroundColor)
  }
  if (value.pullToRefresh) {
    modifier.pullToRefresh(value.pullToRefresh)
  }
  if (value.refreshOffset) {
    modifier.refreshOffset(value.refreshOffset)
  }
  // 创建NodeContent插槽对象用于Refresh子组件挂载。
  let nodeSlot = new NodeContent();
  // 通过ComponentContent创建Refresh组件并将它封装起来。
  let content = new ComponentContent(uiContent!, wrapBuilder<[RefreshAttribute]>(mixedRefresh),
    {
      isRefreshing: value.isRefreshing,
      modifier: modifier,
      slot: nodeSlot,
      onRefreshing: value.onRefreshing,
      onOffsetChange: value.onOffsetChange
    });
  // 将Refresh组件的封装对象及其子组件插槽对象传递给Native侧。
  return { content: content, childSlot: nodeSlot };
}

// 定义Refresh组件的更新函数,用于Native侧更新。
// 在更新场景下,需要将Refresh组件的封装对象及其子组件插槽对象返回,防止组件重新创建。
export function updateMixedRefresh(refresh: ComponentContent, childSlot: NodeContent,
  value: NativeRefreshAttribute): void {
  let modifier = new RefreshModifier();
  if (value.width) {
    modifier.width(value.width)
  }
  if (value.height) {
    modifier.height(value.height)
  }
  if (value.backgroundColor) {
    modifier.backgroundColor(value.backgroundColor)
  }
  if (value.pullToRefresh) {
    modifier.pullToRefresh(value.pullToRefresh)
  }
  if (value.refreshOffset) {
    modifier.refreshOffset(value.refreshOffset)
  }
  // 调用ComponentContent的update接口进行更新。
  refresh.update({
    isRefreshing: value.isRefreshing,
    modifier: modifier,
    slot: childSlot,
    onRefreshing: value.onRefreshing,
    onOffsetChange: value.onOffsetChange
  })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  1. 将创建和更新函数注册给Native侧。
// entry.ets
import nativeNode from 'libentry.so';
import { NodeContent } from '@ohos.arkui.node';
import { createMixedRefresh, updateMixedRefresh } from './MixedModule'

@Entry
@Component
struct Index {
  private rootSlot = new NodeContent();
  @State @Watch('changeNativeFlag') showNative: boolean = false;

  aboutToAppear(): void {
    // 设置uiContext;
    AppStorage.setOrCreate("context", this.getUIContext());
    // 设置混合模式下的builder函数。
    nativeNode.registerCreateMixedRefreshNode(createMixedRefresh);
    nativeNode.registerUpdateMixedRefreshNode(updateMixedRefresh);
  }

  changeNativeFlag(): void {
    if (this.showNative) {
      // 创建NativeModule组件挂载
      nativeNode.createNativeRoot(this.rootSlot)
    } else {
      // 销毁NativeModule组件
      nativeNode.destroyNativeRoot()
    }
  }

  build() {
    Column() {
      Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => {
        this.showNative = !this.showNative
      })
      Row() {
        // ArkTS插入Native组件。
        ContentSlot(this.rootSlot)
      }.layoutWeight(1)
    }
    .width('100%')
    .height('100%')
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

// native_init.cpp
#include "ArkUIMixedRefresh.h"
#include "NativeEntry.h"
#include "napi/native_api.h"

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"createNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr},
        // 注册混合模式创建方法。
        {"registerCreateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterCreateRefresh, nullptr,
         nullptr, nullptr, napi_default, nullptr},
        // 注册混合模式更新方法。
        {"registerUpdateMixedRefreshNode", nullptr, NativeModule::ArkUIMixedRefresh::RegisterUpdateRefresh, nullptr,
         nullptr, nullptr, napi_default, nullptr},
        {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default,
         nullptr}};
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  1. Native侧通过Node-API保存创建和更新函数,用于后续调用。
// ArkUIMixedRefresh.h
// 混合模式交互类。

#ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H
#define MYAPPLICATION_ARKUIMIXEDREFRESH_H

#include "ArkUIMixedNode.h"

#include 

#include 
#include 

namespace NativeModule {

class ArkUIMixedRefresh : public ArkUIMixedNode {
public:
    static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info);
    static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info);
};

} // namespace NativeModule

#endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

// ArkUIMixedRefresh.cpp
// 混合模式交互类。

#include "ArkUIMixedRefresh.h"
#include 

namespace NativeModule {
namespace {
napi_env g_env;
napi_ref g_createRefresh;
napi_ref g_updateRefresh;
} // namespace

napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    g_env = env;
    napi_ref refer;
    // 创建引用之后保存,防止释放。
    napi_create_reference(env, args[0], 1, &refer);

    g_createRefresh = refer;
    return nullptr;
}

napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    g_env = env;
    napi_ref refer;
    // 创建引用之后保存,防止释放。
    napi_create_reference(env, args[0], 1, &refer);

    g_updateRefresh = refer;
    return nullptr;
}

} // namespace NativeModule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  1. 抽象混合模式下组件的基类,用于通用逻辑管理。
// ArkUIMixedNode.h
// 混合模式基类。

#ifndef MYAPPLICATION_ARKUIMIXEDNODE_H
#define MYAPPLICATION_ARKUIMIXEDNODE_H

#include 
#include 

#include "ArkUIBaseNode.h"
#include "NativeModule.h"

namespace NativeModule {

// Wrap ArkTS Node
class ArkUIMixedNode : public ArkUIBaseNode {
public:
    ArkUIMixedNode(ArkUI_NodeHandle handle, napi_env env, napi_ref componentContent)
        : ArkUIBaseNode(handle), env_(env), componentContent_(componentContent) {}

    // 在基类析构的时候需要把混合模式在ArkTS侧的对象释放掉。
    ~ArkUIMixedNode() override { napi_delete_reference(env_, componentContent_); }

protected:
    napi_env env_;
    napi_ref componentContent_;
};

} // namespace NativeModule

#endif // MYAPPLICATION_ARKUIMIXEDNODE_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  1. 实现Refresh组件的混合模式封装对象。
// ArkUIMixedRefresh.h
// Refresh混合模式在Native侧的封装对象。

#ifndef MYAPPLICATION_ARKUIMIXEDREFRESH_H
#define MYAPPLICATION_ARKUIMIXEDREFRESH_H

#include "ArkUIMixedNode.h"
#include "ArkUIBaseNode.h"

#include 

#include 
#include 

namespace NativeModule {

// 定义Native侧和ArkTS侧的交互数据结构。
struct NativeRefreshAttribute {
    std::optional isRefreshing;
    std::optional width;
    std::optional height;
    std::optional backgroundColor;
    std::optional refreshOffset;
    std::optional pullToRefresh;
    std::function onRefreshing;
    std::function onOffsetChange;
};

class ArkUIMixedRefresh : public ArkUIMixedNode {
public:
    // 调用ArkTS的方法创建Refresh组件。
    static const std::shared_ptr Create(const NativeRefreshAttribute &attribute);

    ArkUIMixedRefresh(ArkUI_NodeHandle handle, ArkUI_NodeContentHandle contentHandle, napi_env env,
                      napi_ref componentContent, napi_ref nodeContent)
        : ArkUIMixedNode(handle, env, componentContent), contentHandle_(contentHandle), nodeContent_(nodeContent) {}

    ArkUIMixedRefresh() : ArkUIMixedNode(nullptr, nullptr, nullptr) {}

    ~ArkUIMixedRefresh() override { napi_delete_reference(env_, nodeContent_); } // 释放子节点占位组件插槽对象。

    void SetWidth(float width) { attribute_.width = width; }

    void SetHeight(float height) { attribute_.height = height; }

    void SetBackgroundColor(uint32_t color) { attribute_.backgroundColor = color; }

    void SetRefreshState(bool isRefreshing) { attribute_.isRefreshing = isRefreshing; }

    void SetPullToRefresh(bool pullToRefresh) { attribute_.pullToRefresh = pullToRefresh; }

    void SetRefreshOffset(float offset) { attribute_.refreshOffset = offset; }

    void SetRefreshCallback(const std::function &callback) { attribute_.onRefreshing = callback; }

    void SetOnOffsetChange(const std::function &callback) { attribute_.onOffsetChange = callback; }

    // 避免频繁跨语言,在Native侧缓存属性事件,批量通知。
    void FlushMixedModeCmd();

    static napi_value RegisterCreateRefresh(napi_env env, napi_callback_info info);
    static napi_value RegisterUpdateRefresh(napi_env env, napi_callback_info info);

protected:
    void OnAddChild(const std::shared_ptr &child) override {
        assert(contentHandle_);
        // 使用NodeContent挂载组件(可以使用ArkTS在Native侧通过ComponnetContent的转化对象,也可以是纯Native组件)到ArkTS组件下面。
        OH_ArkUI_NodeContent_AddNode(contentHandle_, child->GetHandle());
    }

    void OnRemoveChild(const std::shared_ptr &child) override {
        assert(contentHandle_);
        // 使用NodeContent卸载组件。
        OH_ArkUI_NodeContent_RemoveNode(contentHandle_, child->GetHandle());
    }

    void OnInsertChild(const std::shared_ptr &child, int32_t index) override {
        assert(contentHandle_);
        // 使用NodeContent插入组件。
        OH_ArkUI_NodeContent_InsertNode(contentHandle_, child->GetHandle(), index);
    }

private:
    // 使用napi接口创建ArkTS侧的数据结构。
    static napi_value CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData);

    ArkUI_NodeContentHandle contentHandle_;
    napi_ref nodeContent_;
    NativeRefreshAttribute attribute_;
};

} // namespace NativeModule

#endif // MYAPPLICATION_ARKUIMIXEDREFRESH_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

相关实现类说明:

#include "ArkUIMixedRefresh.h"
#include 

namespace NativeModule {
namespace {
napi_env g_env;
napi_ref g_createRefresh;
napi_ref g_updateRefresh;
} // namespace

// 使用Napi接口创建与ArkTS侧交互的数据结构,用于Refresh组件的创建和更新。
napi_value ArkUIMixedRefresh::CreateRefreshAttribute(const NativeRefreshAttribute &attribute, void *userData) {
    napi_property_descriptor desc[] = {
        {"width", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
        {"height", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
        {"backgroundColor", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
        {"pullToRefresh", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
        {"isRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
        {"refreshOffset", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
        {"onRefreshing", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
        {"onOffsetChange", nullptr, nullptr, nullptr, nullptr, nullptr, napi_default, userData},
    };
    if (attribute.width) {
        napi_value width;
        napi_create_double(g_env, attribute.width.value(), &width);
        desc[0].value = width;
    }
    if (attribute.height) {
        napi_value height;
        napi_create_double(g_env, attribute.height.value(), &height);
        desc[1].value = height;
    }
    if (attribute.backgroundColor) {
        napi_value backgroundColor;
        napi_create_uint32(g_env, attribute.backgroundColor.value(), &backgroundColor);
        desc[2].value = backgroundColor;
    }
    if (attribute.pullToRefresh) {
        napi_value pullToRefresh;
        napi_create_int32(g_env, attribute.pullToRefresh.value(), &pullToRefresh);
        desc[3].value = pullToRefresh;
    }
    if (attribute.isRefreshing) {
        napi_value isRefreshing;
        napi_create_int32(g_env, attribute.isRefreshing.value(), &isRefreshing);
        desc[4].value = isRefreshing;
    }
    if (attribute.refreshOffset) {
        napi_value refreshOffset;
        napi_create_double(g_env, attribute.refreshOffset.value(), &refreshOffset);
        desc[5].value = refreshOffset;
    }
    if (attribute.onRefreshing) {
        OH_LOG_INFO(LOG_APP, "onRefreshing start");
        desc[6].method = [](napi_env env, napi_callback_info info) -> napi_value {
            OH_LOG_INFO(LOG_APP, "onRefreshing callback");
            size_t argc = 0;
            napi_value args[0];
            void *data;
            napi_get_cb_info(env, info, &argc, args, nullptr, &data);
            auto refresh = reinterpret_cast(data);
            if (refresh && refresh->attribute_.onRefreshing) {
                refresh->attribute_.onRefreshing();
            }
            return nullptr;
        };
    }
    if (attribute.onOffsetChange) {
        OH_LOG_INFO(LOG_APP, "onOffsetChange start");
        desc[7].method = [](napi_env env, napi_callback_info info) -> napi_value {
            OH_LOG_INFO(LOG_APP, "onOffsetChange callback");
            size_t argc = 1;
            napi_value args[1] = {nullptr};
            void *data;
            napi_get_cb_info(env, info, &argc, args, nullptr, &data);
            double offset = 0.0;
            napi_get_value_double(env, args[0], &offset);
            auto refresh = reinterpret_cast(data);
            if (refresh && refresh->attribute_.onOffsetChange) {
                refresh->attribute_.onOffsetChange(offset);
            }
            return nullptr;
        };
    }
    napi_value refreshAttribute = nullptr;
    auto result = napi_create_object_with_properties(g_env, &refreshAttribute, sizeof(desc) / sizeof(desc[0]), desc);
    if (result != napi_ok) {
        return nullptr;
    }
    return refreshAttribute;
}

// 创建ArkTS侧的组件并保存在Native侧的封装对象中。
const std::shared_ptr ArkUIMixedRefresh::Create(const NativeRefreshAttribute &attribute) {
    napi_handle_scope scope;
    napi_open_handle_scope(g_env, &scope);
    auto refresh = std::make_shared();
    auto refreshAttribute = CreateRefreshAttribute(attribute, refresh.get());
    if (refreshAttribute == nullptr) {
        napi_close_handle_scope(g_env, scope);
        return nullptr;
    }
    napi_value result = nullptr;
    napi_value argv[1] = {refreshAttribute};
    napi_value createRefresh = nullptr;
    napi_get_reference_value(g_env, g_createRefresh, &createRefresh);
    // 调用ArkTS的Create函数创建ArkTS的ComponentContent。
    napi_call_function(g_env, nullptr, createRefresh, 1, argv, &result);

    // 获取ArkTS的Refresh组件。
    napi_value componentContent = nullptr;
    napi_get_named_property(g_env, result, "content", &componentContent);
    ArkUI_NodeHandle handle;
    OH_ArkUI_GetNodeHandleFromNapiValue(g_env, componentContent, &handle);
    assert(handle);
    // 获取ArkTS的Refresh组件的子组件插槽。
    napi_value nodeContent = nullptr;
    napi_get_named_property(g_env, result, "childSlot", &nodeContent);
    ArkUI_NodeContentHandle contentHandle;
    OH_ArkUI_GetNodeContentFromNapiValue(g_env, nodeContent, &contentHandle);
    assert(contentHandle);
    // 保存ArkTS的ComponentContent用于防止ArkTS侧对象释放以及后续的更新。
    napi_ref componentContentRef;
    napi_create_reference(g_env, componentContent, 1, &componentContentRef);
    // 保存ArkTS的NodeContent用于防止ArkTS侧对象释放以及后续的更新。
    napi_ref nodeContentRef;
    napi_create_reference(g_env, nodeContent, 1, &nodeContentRef);
    // 更新Refresh组件相关参数。
    refresh->handle_ = handle;
    refresh->env_ = g_env;
    refresh->componentContent_ = componentContentRef;
    refresh->nodeContent_ = nodeContentRef;
    refresh->contentHandle_ = contentHandle;
    refresh->attribute_ = attribute;
    return refresh;
}
// 更新函数实现。
void ArkUIMixedRefresh::FlushMixedModeCmd() {
    napi_handle_scope scope;
    napi_open_handle_scope(g_env, &scope);
    // 创建调用ArkTS接口入参。
    auto refreshAttribute = CreateRefreshAttribute(attribute_, this);
    if (refreshAttribute == nullptr) {
        napi_close_handle_scope(g_env, scope);
        return;
    }
    // 获取更新接口的剩余两个接口参数。
    napi_value componentContent = nullptr;
    napi_get_reference_value(g_env, componentContent_, &componentContent);
    napi_value nodeContent = nullptr;
    napi_get_reference_value(g_env, nodeContent_, &nodeContent);

    napi_value argv[3] = {componentContent, nodeContent, refreshAttribute};
    napi_value updateRefresh = nullptr;
    napi_get_reference_value(g_env, g_updateRefresh, &updateRefresh);
    // 调用ArkTS的Update函数进行更新。
    napi_value result = nullptr;
    napi_call_function(g_env, nullptr, updateRefresh, 3, argv, &result);
}

napi_value ArkUIMixedRefresh::RegisterCreateRefresh(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    g_env = env;
    napi_ref refer;
    napi_create_reference(env, args[0], 1, &refer);

    g_createRefresh = refer;
    return nullptr;
}

napi_value ArkUIMixedRefresh::RegisterUpdateRefresh(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    g_env = env;
    napi_ref refer;
    napi_create_reference(env, args[0], 1, &refer);

    g_updateRefresh = refer;
    return nullptr;
}

} // namespace NativeModule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  1. 使用 接入ArkTS页面 章节的页面结构,并沿用 定时器模块相关简单实现 ,将Refresh组件作为文本列表的父组件。
// MixedRefreshExample.h
// 混合模式示例代码。

#ifndef MYAPPLICATION_MIXEDREFRESHEXAMPLE_H
#define MYAPPLICATION_MIXEDREFRESHEXAMPLE_H

#include "ArkUIBaseNode.h"
#include "ArkUIMixedRefresh.h"
#include "TextListExample.h"
#include "UITimer.h"

#include 

namespace NativeModule {

std::shared_ptr CreateMixedRefreshList(napi_env env) {
    auto list = CreateTextListExample();
    // 混合模式创建Refresh组件并挂载List组件。
    NativeRefreshAttribute nativeRefreshAttribute{
        .backgroundColor = 0xFF89CFF0, .refreshOffset = 64, .pullToRefresh = true};
    auto refresh = ArkUIMixedRefresh::Create(nativeRefreshAttribute);
    refresh->AddChild(list);

    // 设置混合模式下的事件。
    refresh->SetOnOffsetChange(
        [](float offset) { OH_LOG_INFO(LOG_APP, "on refresh offset changed: %{public}f", offset); });
    refresh->SetRefreshCallback([refreshPtr = refresh.get(), env]() {
        OH_LOG_INFO(LOG_APP, "on refreshing");
        // 启动定时器,模拟数据获取。
        CreateNativeTimer(env, refreshPtr, 1, [](void *userData, int32_t count) {
            // 数据获取后关闭刷新。
            auto refresh = reinterpret_cast(userData);
            refresh->SetRefreshState(false);
            refresh->FlushMixedModeCmd();
        });
    });

    // 更新事件到ArkTS侧。
    refresh->FlushMixedModeCmd();
    return refresh;
}

} // namespace NativeModule

#endif // MYAPPLICATION_MIXEDREFRESHEXAMPLE_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

替换入口组件创建为下拉刷新文本列表。

#include "NativeEntry.h"

#include "ArkUIMixedRefresh.h"
#include "MixedRefreshExample.h"
#include "TextListExample.h"

#include 
#include 
#include 
#include 

namespace NativeModule {

napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取NodeContent
    ArkUI_NodeContentHandle contentHandle;
    OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
    NativeEntry::GetInstance()->SetContentHandle(contentHandle);

    // 创建Refresh文本列表
    auto refresh = CreateMixedRefreshList(env);

    // 保持Native侧对象到管理类中,维护生命周期。
    NativeEntry::GetInstance()->SetRootNode(refresh);
    return nullptr;
}

napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
    // 从管理类中释放Native侧对象。
    NativeEntry::GetInstance()->DisposeRootNode();
    return nullptr;
}

} // namespace NativeModule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

鸿蒙全栈开发全新学习指南

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以要有一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

鸿蒙开发学习资料领取!!!
微信名片
注:本文转载自blog.csdn.net的OpenHarmony_小贾的文章"https://blog.csdn.net/maniuT/article/details/140281257"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top