React Native 的 EventEmitter 双向通信 ,本质是 JS 和 Native 之间通过事件机制互相通知。
它和普通 Native Module 方法调用不同:
- Native Module:JS 主动调用 Native
- EventEmitter:Native 和 JS 都可以主动发送事件
通信模型:
yaml
JS
|
| emit / addListener
|
React Native Bridge
|
|
Native
一、JS → Native(主动调用)
这个不是 EventEmitter 最典型场景,一般用 Native Module。
例如:
JS:
ini
NativeModules.DeviceModule.start();
Native:
typescript
@ReactMethod
public void start(){
//执行原生逻辑
}
流程:
arduino
JS
|
Bridge
|
Native Module
|
Java/Kotlin
二、Native → JS(EventEmitter)
这是 EventEmitter 最常见用途。
例如:
Android 检测到:
- 蓝牙状态变化
- GPS变化
- 推送消息
- 传感器数据
Native:
csharp
sendEvent(
"onLocationChanged",
params
);
JS监听:
ini
DeviceEventEmitter.addListener(
"onLocationChanged",
data=>{
console.log(data);
}
);
流程:
arduino
Android
|
emit事件
|
Bridge
|
JS Listener
三、Android实现 EventEmitter
1. Native Module继承
java
public class DeviceModule
extends ReactContextBaseJavaModule {
private ReactApplicationContext context;
public DeviceModule(
ReactApplicationContext context
){
super(context);
this.context=context;
}
@Override
public String getName(){
return "DeviceModule";
}
}
2. 发送事件
csharp
private void sendEvent(
String eventName,
WritableMap params
){
context
.getJSModule(
DeviceEventManagerModule.RCTDeviceEventEmitter.class
)
.emit(
eventName,
params
);
}
这里:
RCTDeviceEventEmitter
就是 RN 的事件桥。
3. 调用
比如:
kotlin
WritableMap data =
Arguments.createMap();
data.putString(
"message",
"hello JS"
);
sendEvent(
"DeviceEvent",
data
);
四、JS监听
RN 新版本推荐:
ini
import {
NativeEventEmitter,
NativeModules
} from 'react-native';
const {
DeviceModule
}=NativeModules;
const emitter =
new NativeEventEmitter(DeviceModule);
const subscription =
emitter.addListener(
"DeviceEvent",
data=>{
console.log(data);
}
);
取消监听:
csharp
subscription.remove();
否则容易:
Memory Leak
五、JS → Native事件
如果 JS 想发事件给 Native:
例如:
JS:
php
DeviceEventEmitter.emit(
"Login",
{
user:"Tom"
}
);
但是:
Native 默认不能直接监听 JS EventEmitter。
通常做法:
JS调用Native Module
css
NativeModules.UserModule.login(
{
user:"Tom"
}
);
Native:
typescript
@ReactMethod
public void login(
ReadableMap data
){
}
也就是说:
sql
JS ---> Native
推荐:
Native Module
不是 EventEmitter
六、完整双向模型
markdown
JS
NativeEventEmitter
↑
|
Native ---> JS
emit事件
↓
Native Module
↑
JS ---> Native
method调用
Native
七、实际项目例子:扫码
JS启动扫码
ini
Scanner.start();
↓
Native:
scss
startCamera();
↓
扫码成功:
css
emit(
"ScanResult",
{
code:"123456"
}
);
↓
JS:
javascript
scannerEmitter.addListener(
"ScanResult",
(result)=>{
console.log(result.code);
});
八、RN 新架构(TurboModule)
旧架构:
arduino
JS
|
Bridge
|
EventEmitter
|
Native
新架构:
JS
|
JSI
|
TurboModule
|
Native
事件通常使用:
- TurboModule
- EventEmitter interface
- Codegen
例如:
TypeScript:
typescript
export interface Spec
extends TurboModule {
readonly onChange:
EventEmitter<string>;
}
Codegen 自动生成绑定。
总结
| 方向 | 推荐方式 |
|---|---|
| JS调用Native | Native Module |
| Native通知JS | NativeEventEmitter |
| 持续数据流 | EventEmitter |
| 一次请求返回 | Promise/Callback |
| 新架构 | TurboModule + EventEmitter |
实际开发中:
- 蓝牙状态
- 推送
- GPS
- NFC
- 扫码
- 原生播放器状态
基本都是:
markdown
JS调用Native启动
↓
Native持续emit事件
↓
JS监听更新UI
这就是 RN EventEmitter 最典型的双向通信模式。