【大前端】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
  • 封装要点:统一接口、模块化、尽量隐藏平台差异

相关推荐
2501_915106322 小时前
移动端网页调试实战,iOS WebKit Debug Proxy 的应用与替代方案
android·前端·ios·小程序·uni-app·iphone·webkit
可乐+冰03 小时前
Android 编写高斯模糊功能
android·人工智能·opencv
睡美人的小仙女1274 小时前
在 Vue 前端(Vue2/Vue3 通用)载入 JSON 格式的动图
前端·javascript·vue.js
yuanyxh4 小时前
React Native 初体验
前端·react native·react.js
程序视点5 小时前
2025最佳图片无损放大工具推荐:realesrgan-gui评测与下载指南
前端·后端
程序视点6 小时前
2023最新HitPaw免注册版下载:一键去除图片视频水印的终极教程
前端
xzkyd outpaper6 小时前
Android中APK包含哪些内容?
android
蹦极的考拉6 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
安卓开发者7 小时前
Android Glide最佳实践:高效图片加载完全指南
android·glide