当前位置: 首页 > news >正文

【大前端】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

// 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. 最佳实践

  1. 模块化封装

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

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

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

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

http://www.xdnf.cn/news/1379773.html

相关文章:

  • Cesium入门教程(二)环境搭建(HTML版)
  • leetcode 525 连续数组
  • 【PostgreSQL内核学习:通过 ExprState 提升哈希聚合与子计划执行效率(二)】
  • MySQL 与 ClickHouse 深度对比:架构、性能与场景选择指南
  • 【第三方网站运行环境测试:服务器配置(如Nginx/Apache)的WEB安全测试重点】
  • R 语言 ComplexUpset 包实战:替代 Venn 图的高级集合可视化方案
  • 基于mac的智能语音处理与应用开发-环境部署
  • HTML应用指南:利用POST请求获取全国中国工商银行网点位置信息
  • 【mysql】SQL HAVING子句详解:分组过滤的正确姿势
  • TUN模式端口冲突 启动失败如何解决?
  • 点评项目(Redis中间件)第二部分Redis基础
  • PostgreSQL 流复制与逻辑复制性能优化与故障切换实战经验分享
  • Java集合操作:Apache Commons Collections4启示录
  • 【Web】JWT(JSON Web Token)技术详解
  • 客户案例 | 柳钢集团×甄知科技,燕千云ITSM打造智能服务新生态
  • Mac 开发环境与配置操作速查表
  • 基于django的梧桐山水智慧旅游平台设计与开发(代码+数据库+LW)
  • 破译心智密码:神经科学如何为下一代自然语言处理绘制语义理解的蓝图
  • 磁力计校准矩阵求解方法解析
  • 从体验到系统工程丨上手评测国内首款 AI 电商 App
  • 图书管理系统练习项目源码-前后端分离-【Java版】
  • Python Imaging Library (PIL) 全面指南:PIL基础入门-图像滤波与处理技术
  • week5-[一维数组]去重
  • 机器学习基本概述
  • STM32F407与LAN8720A以太网通信实现指南
  • GraphRAG技术深度解析:重新定义智能问答的未来
  • 【赵渝强老师】MySQL数据库的多实例环境
  • Redis 连接数爆炸:连接池配置错误踩坑记录
  • Electron 简介:Node.js 桌面开发的起点
  • 华为云OBS+HMS+EMRonEC2+HiveSparkFlink+GaussDB