React Native 原生模块封装:Android Kotlin 与 iOS Swift 双向通信的统一接口设计

设计目标
  1. 创建跨平台统一的 JavaScript 接口
  2. 实现原生到 JavaScript 的事件推送
  3. 支持 JavaScript 到原生的方法调用
  4. 保证类型安全的数据传输
统一接口架构
graph LR
    JS[JavaScript 层] --> Bridge[React Native Bridge]
    Bridge --> Android[Android Kotlin 模块]
    Bridge --> iOS[iOS Swift 模块]
    Android --> Event[原生事件]
    iOS --> Event
    Event --> JS

核心实现步骤
1. JavaScript 统一接口层
import { NativeModules, NativeEventEmitter } from 'react-native';

const { UnifiedNativeModule } = NativeModules;
const eventEmitter = new NativeEventEmitter(UnifiedNativeModule);

export default {
  // 调用原生方法
  callNativeMethod: (methodName, params) => 
    UnifiedNativeModule.invokeMethod(methodName, params),

  // 监听原生事件
  addEventListener: (eventName, handler) => 
    eventEmitter.addListener(eventName, handler),

  // 移除事件监听
  removeListener: (subscription) => 
    subscription.remove()
};

2. Android Kotlin 实现
@ReactModule(name = "UnifiedNativeModule")
class UnifiedModule(reactContext: ReactApplicationContext) : 
    ReactContextBaseJavaModule(reactContext) {

    private val eventEmitter: RCTDeviceEventEmitter? by lazy {
        reactContext.getJSModule(RCTDeviceEventEmitter::class.java)
    }

    override fun getName() = "UnifiedNativeModule"

    @ReactMethod
    fun invokeMethod(methodName: String, params: ReadableMap, promise: Promise) {
        when (methodName) {
            "getDeviceInfo" -> promise.resolve(getDeviceInfo())
            "calculate" -> promise.resolve(calculate(params))
            else -> promise.reject("UNKNOWN_METHOD", "Method not implemented")
        }
    }

    // 原生主动推送事件
    fun sendEvent(eventName: String, data: WritableMap) {
        eventEmitter?.emit(eventName, data)
    }

    private fun getDeviceInfo(): WritableMap {
        return Arguments.createMap().apply {
            putString("os", "Android")
            putInt("apiLevel", Build.VERSION.SDK_INT)
        }
    }
}

3. iOS Swift 实现
@objc(UnifiedNativeModule)
class UnifiedModule: RCTEventEmitter {
    private var hasListeners = false
    
    override func supportedEvents() -> [String]! {
        return ["onDataUpdate", "onStatusChange"]
    }
    
    override func startObserving() {
        hasListeners = true
    }
    
    override func stopObserving() {
        hasListeners = false
    }
    
    @objc(invokeMethod:params:resolver:rejecter:)
    func invokeMethod(
        _ methodName: String,
        params: [String: Any],
        resolver: @escaping RCTPromiseResolveBlock,
        rejecter: @escaping RCTPromiseRejectBlock
    ) {
        switch methodName {
        case "getDeviceInfo":
            resolver(getDeviceInfo())
        case "calculate":
            resolver(calculate(params))
        default:
            rejecter("UNKNOWN_METHOD", "Method not implemented", nil)
        }
    }
    
    // 原生主动推送事件
    func sendEvent(name: String, data: [String: Any]) {
        if hasListeners {
            sendEvent(withName: name, body: data)
        }
    }
    
    private func getDeviceInfo() -> [String: Any] {
        return [
            "os": "iOS",
            "version": UIDevice.current.systemVersion
        ]
    }
}

数据类型映射
JavaScript 类型 Android 类型 iOS 类型
Number Double NSNumber
String String NSString
Boolean Boolean BOOL
Array ReadableArray NSArray
Object ReadableMap NSDictionary
双向通信示例
// JavaScript 调用原生方法
import NativeModule from './NativeModule';

const result = await NativeModule.callNativeMethod('calculate', {
  a: 5,
  b: 3,
  operator: '+'
});

// 监听原生事件
const subscription = NativeModule.addEventListener('onDataUpdate', (data) => {
  console.log('Received data:', data);
});

// 移除监听
subscription.remove();

关键设计原则
  1. 接口一致性:两端实现相同的方法签名和事件名称
  2. 错误处理:统一使用 Promise rejection 传递错误
  3. 内存管理
    • Android:使用 WeakReference 避免内存泄漏
    • iOS:正确管理事件监听生命周期
  4. 线程安全
    • Android:确保在 UI 线程更新视图
    • iOS:使用主线程队列处理 UI 更新
性能优化建议
  1. 使用批量数据传输代替频繁小数据传递
  2. 复杂数据序列化采用 Protobuf 格式
  3. 高频事件添加节流(throttle)控制
  4. 使用 @ReactMethod(isBlockingSynchronousMethod = true) 处理同步调用

该设计实现了跨平台统一的通信接口,开发者只需关注 JavaScript 层的业务逻辑,无需处理平台差异,同时保持原生模块的高性能和安全性。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐