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 接口,并重写 createNativeModulescreateViewManagers 两个方法。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.javagetPackages 方法中注册 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