原生往js层传递消息的方式
*iOS端是继承RCTEventEmitter,然后调用sendEventWithName方法
[self sendEventWithName:@"EventReminder" body:nil];
*Android端
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("EventReminder", null);
android
通过 RCTDeviceEventEmitter 模块进行原生与js的交互,所以在js层直接使用 RCTDeviceEventEmitter来注册监听
例如:
var emitter = require("RCTDeviceEventEmitter")
emitter.addListener("EventReminder",(e)=>{
console.log("guangy get event in RCTDeviceEventEmitter")
})
或者
import {DeviceEventEmitter} from "react-native"
DeviceEventEmitter.addListener("EventReminder",(e)=>{
})
对应的调用方式
import {DeviceEventEmitter} from "react-native"
或
import {DeviceEventEmitter} from "react-native"
DeviceEventEmitter.emit("EventReminder", params);
iOS
android 上两种注册方式都不会响应回调,iOS需要创建RCTEventEmitter的子类,在子类中处理js端的注册监听
针对sendEventWithName
方法的实现,查看源码
- (void)sendEventWithName:(NSString *)eventName body:(id)body
{
...(省略部分代码)
`关键代码`
if (_listenerCount > 0) {
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter"
method:@"emit"
args:body ? @[eventName, body] : @[eventName]
completion:NULL];
}
...(省略部分代码)
}
其实RCTEventEmitter
也是通过RCTDeviceEventEmitter
进行注册通知的,但是它有一个控制值_listenerCount
,而_listenerCount
的数据类型为NSInteger
所以默认初始值为0,其中_listenerCount
代码的逻辑查看源码(主要):
// _listenerCount
增加
RCT_EXPORT_METHOD(addListener:(NSString *)eventName)
{
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
eventName, [self class], [[self supportedEvents] componentsJoinedByString:@"`, `"]);
}
_listenerCount++;
if (_listenerCount == 1) {
[self startObserving];
}
}
// _listenerCount
减少
RCT_EXPORT_METHOD(removeListeners:(double)count)
{
int currentCount = (int)count;
if (RCT_DEBUG && currentCount > _listenerCount) {
RCTLogError(@"Attempted to remove more %@ listeners than added", [self class]);
}
_listenerCount = MAX(_listenerCount - currentCount, 0);
if (_listenerCount == 0) {
[self stopObserving];
}
}
所以js层必须通过如下方式进行addListener
方法的调用:
const { RNCarrotEmitter, RNListenerManager } = NativeModules;
const listenerManager = new NativeEventEmitter(RNListenerManager);
// 调用 addListener 从而修改_listenerCount 属性
listenerManager.addListener(name, listenerResult);
查看NativeEventEmitter
代码块中关于addListener
方法调用:
addListener(
eventType: string,
listener: Function,
context: ?Object,
): EmitterSubscription {
if (this._nativeModule != null) {
this._nativeModule.addListener(eventType);
}
return super.addListener(eventType, listener, context);
}
这里调用了原生模块的addListener
方法(即RCTEventEmitter中的addListener
方法),使_listenerCount
加1。所以在iOS端,因为原生代码中通过继承RCTEventEmitter类来发送消息,js层就必须使用NativeEventEmitter来注册监听,否则的话,原生层连消息都不会发出去。但是在Android端,因为底层实现就是直接给RCTDeviceEventEmitter发消息,不像iOS端有RCTEventEmitter类的那一套逻辑。
网友评论