前言:本文主要讲直接在项目中自定义TurboModule,通过TurboModule调用鸿蒙api。前提是已经运行成功RN鸿蒙化工程

1.声明 JavaScript 接口

新架构要求必须使用强类型风格语言声明 JavaScript 接口(Flow 和 TypeScript 皆可)。Codegen 会根据这些接口声明来生成强类型的语言,其中包括 C++、Objective-C 和 Java。

对于声明类型的代码文件必须满足以下两点要求:

  1. 文件必须使用 Native<MODULE_NAME>命名,在使用 Flow 时,以 .js 或 .jsx 为后缀名;在使用 Typescript 时,以 .ts 或 .tsx 为后缀名。Codegen 只会找到匹配这些命名规则的文件;
  2. 代码中必须要输出 TurboModuleRegistrySpec 对象
NativeCalculator.ts
import type { TurboModule } from "react-native/Libraries/TurboModule/RCTExport";
import { TurboModuleRegistry } from "react-native";

export interface Spec extends TurboModule {
  add(a: number, b: number): Promise<number>;
}

export default TurboModuleRegistry.get<Spec>("RTNCalculator") as Spec | null;

2. Codegen 配置

接下来,需要为 Codegen 和自动链接添加一些配置。Codegen 的作用是生成 C++ 脚手架代码,负责串联 JS 和原生侧。

有一些配置文件在 Android/iOS/HarmonyOS 平台是通用的,而有的仅能在某一平台使用。

2.1 配置 package.json 文件,在工程的package.json中添加如下:
  "harmony": {
    "codegenConfig": {
      "specPaths": [
        "./src/turboModule"
      ]
    }
  }
2.2 配置 package.json 文件,在工程的package.json中添加如下:
"scripts": {
...
"codegen": "react-native codegen-harmony --cpp-output-path ./MyApplication/entry/src/main/cpp/generated --rnoh-module-path ./MyApplication/entry/oh_modules/@rnoh/react-native-openharmony"
}

执行 npm run codegen,日志中有如下产物说明执行成功(MyApplication\entry\src\main\cpp\generated\RTNCalculator.h

MyApplication\entry\src\main\cpp\generated\RTNCalculator.cpp

MyApplication/entry/oh_modules/@rnoh/react-native-openharmony/generated/turboModules/RTNCalculator.ts

• MyApplication\entry\src\main\cpp\generated\RTNCalculator.cpp
• MyApplication\entry\src\main\cpp\generated\RTNCalculator.h

3. 原生代码

HarmonyOS 平台上 Turbo Native Module 的原生代码需执行如下步骤:

  1. 创建用于实现模块的 CalculatorModule.ts
  2. 创建 CalculatorPackage.ts

创建MyApplication/entry/src/main/ets/CalculatorModule.ts

import { TurboModule } from '@rnoh/react-native-openharmony/ts';
import { TM } from "@rnoh/react-native-openharmony/generated/ts"

export class CalculatorModule extends TurboModule implements TM.RTNCalculator.Spec {
    add(a: number, b: number): Promise<number> {
        return new Promise((resolve) => resolve(a + b));
      }
}

这个类实现了模块的功能,它继承了 TurboModule 类,对应 Android 里的 NativeCalculatorSpec。

创建用于实现模块的 MyApplication/entry/src/main/ets/CalculatorModule.ts

import {
  RNPackage,
  TurboModulesFactory,
} from "@rnoh/react-native-openharmony/ts";
import type {
  TurboModule,
  TurboModuleContext,
} from "@rnoh/react-native-openharmony/ts";
import { TM } from "@rnoh/react-native-openharmony/generated/ts";
import { CalculatorModule } from './CalculatorModule';

class CalculatorModulesFactory extends TurboModulesFactory {
  createTurboModule(name: string): TurboModule | null {
    if (name === TM.RTNCalculator.NAME) {
      return new CalculatorModule(this.ctx);
    }
    return null;
  }

  hasTurboModule(name: string): boolean {
    return name === TM.RTNCalculator.NAME;
  }
}

export class CalculatorPackage extends RNPackage {
  createTurboModulesFactory(ctx: TurboModuleContext): TurboModulesFactory {
    return new CalculatorModulesFactory(ctx);
  }
}

4.将 Turbo Native Module 添加到 App,引入 Calculator TurboModule

打开 MyApp/harmony/entry/src/main/ets/RNPackageFactory.ts,添加:

import type {RNPackageContext, RNPackage} from '@rnoh/react-native-openharmony/ts';
+ import {CalculatorPackage} from './CalculatorPackage'
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
+   new CalculatorPackage(ctx),
    ];
}

编译、运行即可。

5.JavaScript侧使用

以下是一个在 App.js 中调用 add 方法的例子:

App.js
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */
import React from "react";
import { useState } from "react";
import type { Node } from "react";
import { SafeAreaView, StatusBar, Text, Button } from "react-native";
import RTNCalculator from "rtn-calculator/src/NativeCalculator.js";

const App: () => Node = () => {
  const [result, setResult] = useState<number | null>(null);
  return (
    <SafeAreaView>
      <StatusBar barStyle={"dark-content"} />
      <Text style={{ marginLeft: 20, marginTop: 20 }}>
        3+7={result ?? "??"}
      </Text>
      <Button
        title="Compute"
        onPress={async () => {
          const value = await RTNCalculator.add(3, 7);
          setResult(value);
        }}
      />
    </SafeAreaView>
  );
};
export default App;

现在,您可以运行 App 并查看在屏幕上显示的组件。

尾声:TurboModule自定义 ,它将TurboModule作为三方库来写的,方便打包为tgz,鸿蒙侧可以打包为har包。本文简化了组织结构,方便在项目中直接添加。

 ohos_react_native: React Native鸿蒙化仓库

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐