React Native 桥接原生模块完整教程

Viewed 1

原生模块简介

有时候一个 React Native 应用需要访问原生平台的 API,比如相机,但默认情况下 JavaScript 无法直接调用这些原生 API。原生模块系统通过将 Java 类的实例暴露给 JavaScript,允许开发者在 JS 代码中执行特定的原生代码。

简单来说,桥接原生主要用于实现 React 层中 JavaScript 无法完成的需求,例如:

  • 复杂、高性能组件:如复杂表格、视频播放器等;
  • 原生层开发能力:如传感器编程、widget 等;
  • 平台属性:如系统信息、设备信息等;
  • 对接三方应用:如相机、相册、地图等。

桥接原生方法

编写并注册原生层方法

  1. 使用 Android Studio 打开项目,找到 android > app > src > main > java > com.rndemo(RN 应用的项目名称)> MainApplication.java。定位到 getPackages 方法,该方法返回 React Native 桥接的各种包,初始时未添加任何自定义包。

  2. 在 com.rndemo 包下新建 rn 文件夹,并在其中创建 RnDemoPackage.java 类。该类需要实现 ReactPackage 接口,并重写 createNativeModules 和 createViewManagers 两个方法。createNativeModules 用于导入 RN 原生模块,createViewManagers 用于导入 RN 原生组件。

  3. createNativeModules 方法返回一个原生模块(NativeModule)的集合,因此需要先创建一个原生模块,例如命名为 AppModule.java。该类需继承 ReactContextBaseJavaModule 并重写 getName 方法。同时,AppModule 需要一个构造函数,可以通过快捷键 Alt + Insert 选择 Constructor,并在弹出的窗口中选择第二个带参数的构造函数。

  4. 若 AppModule 需要向 JavaScript 暴露一个打开手机相册的方法,可以添加 openGallery 方法,并使用 @ReactMethod 注解修饰。该方法中使用的 DeviceUtil 工具类需提前准备,位于 rn 同级目录下的 utils 文件夹中。

最终 AppModule 的代码如下:

package com.rndemo.rn;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.rndemo.utils.DeviceUtil;

public class AppModule extends ReactContextBaseJavaModule {
    public AppModule(@Nullable ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @NonNull
    @Override
    public String getName() {
        // 返回原生模块注册时的名称,JS 层调用时需要知道此名称
        return "CustomApp";
    }

    @ReactMethod
    public void openGallery() {
        if (getCurrentActivity() == null) {
            return;
        }
        DeviceUtil.openGallery(getCurrentActivity());
    }
}
  1. 回到 RnDemoPackage 类,在 createNativeModules 方法中将注册好的 AppModule 添加到模块集合中。

  2. 最后,在 MainApplication.java 的 getPackages 方法中注册 RnDemoPackage。

JS 层调用原生方法

在 JavaScript 层,可以从 NativeModules 中取出注册好的原生模块并调用其方法。示例代码如下:

import React from 'react';
import {StyleSheet, View, Button, NativeModules} from 'react-native';

export default () => {
  return (
    <View style={styles.root}>
      <Button
        title="桥接原生方法"
        onPress={() => {
          const {CustomApp} = NativeModules;
          CustomApp?.openGallery();
        }}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    width: '100%',
    height: '100%',
  },
});

点击按钮即可调用原生方法打开相册。

原生模块暴露带返回值的方法

需要注意的是,从 JS 层调用原生方法是一个异步过程,因此原生层中带返回值的方法不能直接返回,而需要使用 Promise 实现。例如,原生层可以提供一个返回应用版本名称的方法 getVersionName,JS 层通过 Promise 获取返回值。

桥接原生常量

编写并注册原生常量方法

在 AppModule 原生组件中重写 getConstants 方法,以暴露常量给 JavaScript。

JS 层获取原生常量(同步获取)

在 JS 层可以直接同步读取原生模块暴露的常量,无需异步调用。示例中展示了如何获取并显示常量值。

0 Answers
Related