【大前端】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_MODULE
和RCT_EXPORT_METHOD
暴露方法。
- Android:Java/Kotlin → 继承
-
JS 调用时通过
NativeModules
拿到对应的模块,再调用方法。 -
双向通信:
- JS → 原生(方法调用)
- 原生 → JS(事件通知 / 回调 Promise)
2. Android 封装原生能力
(1)新建原生 Module
// 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);}@Overridepublic String getName() {return "MyNative"; // JS 调用时用的名字}// 示例:获取电池电量@ReactMethodpublic void getBatteryLevel(Promise promise) {try {int battery = 80; // 假设写死,实际可用系统 API 获取promise.resolve(battery);} catch (Exception e) {promise.reject("ERROR", e);}}
}
(2)注册 Module
// 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 {@Overridepublic List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {List<NativeModule> modules = new ArrayList<>();modules.add(new MyNativeModule(reactContext));return modules;}@Overridepublic List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {return Collections.emptyList();}
}
在 MainApplication.java
里注册:
packages.add(new MyPackage());
3. iOS 封装原生能力
(1)Objective-C 示例
// MyNativeModule.m
#import <React/RCTBridgeModule.h>@interface RCT_EXTERN_MODULE(MyNative, NSObject)RCT_EXTERN_METHOD(getBatteryLevel:(RCTPromiseResolveBlock)resolverejecter:(RCTPromiseRejectBlock)reject)@end
(2)Swift 示例
@objc(MyNative)
class MyNative: NSObject {@objcfunc getBatteryLevel(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {let battery = 80 // 假设写死resolve(battery)}
}
4. JS 调用
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
WritableMap params = Arguments.createMap();
params.putString("event", "BatteryLow");
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("BatteryEvent", params);
- iOS:使用
RCTEventEmitter
[self sendEventWithName:@"BatteryEvent" body:@{@"event": @"BatteryLow"}];
- JS 监听
import { NativeEventEmitter, NativeModules } from 'react-native';const eventEmitter = new NativeEventEmitter(NativeModules.MyNative);
eventEmitter.addListener('BatteryEvent', (event) => {console.log(event);
});
6. 最佳实践
-
模块化封装:
- 每个功能一个
Native Module
,按业务拆分。 - 统一放在
/native-modules/
目录下,JS 层再封装一层 API。
- 每个功能一个
-
跨平台统一接口:
- 在 JS 层写一个
Battery.ts
,内部判断Platform.OS
调用 Android/iOS 实现。
- 在 JS 层写一个
-
避免直接调用 NativeModules:
-
封装成业务方法,例如:
export async function getBatteryLevel(): Promise<number> {return await NativeModules.MyNative.getBatteryLevel(); }
-
-
新架构 TurboModules(进阶):
- 使用 JSI 直接绑定 C++ → JS 方法,无需 Bridge。
- 更高性能(避免 JSON 序列化)。
📌 总结:
RN 调用原生能力 = JS ↔ Native Module ↔ Android/iOS API
- JS 调用 Native:
NativeModules.MyNative.xxx()
- Native 调用 JS:事件/回调/Promise
- 封装要点:统一接口、模块化、尽量隐藏平台差异