【大前端】React Native 调用 Android、iOS 原生能力封装


📖 React Native 调用 Android、iOS 原生能力封装

1. 原理

React Native 的 核心思想

  • JS 层(React 代码)不能直接调用 Android/iOS 的 API。

  • RN 提供了 Native Module 机制

    • Android :Java/Kotlin → 继承 ReactContextBaseJavaModule,通过 @ReactMethod 暴露方法。
    • iOS :Objective-C/Swift → 使用 RCT_EXPORT_MODULERCT_EXPORT_METHOD 暴露方法。
  • JS 调用时通过 NativeModules 拿到对应的模块,再调用方法。

  • 双向通信

    • JS → 原生(方法调用)
    • 原生 → JS(事件通知 / 回调 Promise)

2. Android 封装原生能力

(1)新建原生 Module

java 复制代码
// MyNativeModule.java
package com.myapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;

public class MyNativeModule extends ReactContextBaseJavaModule {
    MyNativeModule(ReactApplicationContext context) {
        super(context);
    }

    @Override
    public String getName() {
        return "MyNative"; // JS 调用时用的名字
    }

    // 示例:获取电池电量
    @ReactMethod
    public void getBatteryLevel(Promise promise) {
        try {
            int battery = 80; // 假设写死,实际可用系统 API 获取
            promise.resolve(battery);
        } catch (Exception e) {
            promise.reject("ERROR", e);
        }
    }
}

(2)注册 Module

java 复制代码
// MyPackage.java
package com.myapp;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MyPackage implements ReactPackage {
  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();
    modules.add(new MyNativeModule(reactContext));
    return modules;
  }

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }
}

MainApplication.java 里注册:

java 复制代码
packages.add(new MyPackage());

3. iOS 封装原生能力

(1)Objective-C 示例

objc 复制代码
// MyNativeModule.m
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(MyNative, NSObject)

RCT_EXTERN_METHOD(getBatteryLevel:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)

@end

(2)Swift 示例

swift 复制代码
@objc(MyNative)
class MyNative: NSObject {
  @objc
  func getBatteryLevel(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
    let battery = 80 // 假设写死
    resolve(battery)
  }
}

4. JS 调用

tsx 复制代码
import { NativeModules } from 'react-native';
const { MyNative } = NativeModules;

async function checkBattery() {
  try {
    const level = await MyNative.getBatteryLevel();
    console.log("电池电量:", level);
  } catch (e) {
    console.error(e);
  }
}

5. 原生 → JS 的事件通知

有些能力(如推送、传感器数据)需要原生主动回调 JS。

  • Android :使用 DeviceEventManagerModule
java 复制代码
WritableMap params = Arguments.createMap();
params.putString("event", "BatteryLow");
reactContext
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
  .emit("BatteryEvent", params);
  • iOS :使用 RCTEventEmitter
objc 复制代码
[self sendEventWithName:@"BatteryEvent" body:@{@"event": @"BatteryLow"}];
  • JS 监听
tsx 复制代码
import { NativeEventEmitter, NativeModules } from 'react-native';

const eventEmitter = new NativeEventEmitter(NativeModules.MyNative);
eventEmitter.addListener('BatteryEvent', (event) => {
  console.log(event);
});

6. 最佳实践

  1. 模块化封装

    • 每个功能一个 Native Module,按业务拆分。
    • 统一放在 /native-modules/ 目录下,JS 层再封装一层 API。
  2. 跨平台统一接口

    • 在 JS 层写一个 Battery.ts,内部判断 Platform.OS 调用 Android/iOS 实现。
  3. 避免直接调用 NativeModules

    • 封装成业务方法,例如:

      tsx 复制代码
      export async function getBatteryLevel(): Promise<number> {
        return await NativeModules.MyNative.getBatteryLevel();
      }
  4. 新架构 TurboModules(进阶):

    • 使用 JSI 直接绑定 C++ → JS 方法,无需 Bridge。
    • 更高性能(避免 JSON 序列化)。

📌 总结:

RN 调用原生能力 = JS ↔ Native Module ↔ Android/iOS API

  • JS 调用 Native:NativeModules.MyNative.xxx()
  • Native 调用 JS:事件/回调/Promise
  • 封装要点:统一接口、模块化、尽量隐藏平台差异

相关推荐
counterxing2 小时前
我整理了一个免费开发资源目录,还做成了 CLI 和 MCP
前端·agent·ai编程
赏金术士8 小时前
Kotlin 习题集 · 高级篇
android·开发语言·kotlin
子兮曰8 小时前
Bun v1.3.14 深度解析:Image API、HTTP/3、全局虚拟存储与五十项变革
前端·后端·bun
kyriewen9 小时前
今天,百年巨头一次砍了9200人,而一个离职科学家的实话让全网睡不着觉
前端·openai·ai编程
问心无愧051310 小时前
ctf show web 入门42
android·前端·android studio
kyriewen10 小时前
老板逼我上AI,我偷偷在浏览器里跑LLaMA,省下20万API费
前端·react.js·llm
Beginner x_u10 小时前
前端八股整理(手写 02)|数组转树、数组扁平化、随机打乱一个数组
前端·数组·数组转树·数组扁平化
KaMeidebaby10 小时前
卡梅德生物技术快报|禽类成纤维细胞 FISH 实验:鸟类性别染色体基因定位技术实现与数据验证
前端·数据库·其他·百度·新浪微博
没什么本事10 小时前
关于C# panel 添加lable问题 -- 明确X和Y 位置错误
android·java·c#
天若有情67310 小时前
前端高阶性能优化:跳出传统懒加载与预加载,基于用户行为做轻量预判加载
前端·性能优化