有时我们从native发送事件到javascript时希望能够根据javascript的处理结果回调native的相关处理逻辑,RN并没有直接提供相关机制,因此我们往往需要按照以下的方式来进行模拟:
Native发送event到JavaScript
[bridge enqueueJSCall:@"RCTDeviceEventEmitter" method:@"emit" args:@[@"demo", @"Request from Native"] completion:nil];
reactContext.getJSModule(
DeviceEventManagerModule.RCTDeviceEventEmitter.class
).emit("demo", "Request from Native");JavaScript监听event并做处理
import React from 'react'import { NativeModules, DeviceEventEmitter } from 'react-native';const { MyAppManager } = NativeModules;class MyApp extends React.PureComponent {
componentWillMount() {
DeviceEventEmitter.addListener('demo', (params) => { //doSomething....
MyAppManager.invokeCallback({
response: 'Response from JavaScript',
});
});
}
componentWillUnmount() {
DeviceEventEmitter.removeListener('demo');
}
}注册MyAppManager
//MyAppManager.h#import <React/RCTBridgeModule.h>@interface MyAppManager : NSObject <RCTBridgeModule>@end//MyAppManager.m#import "MyAppManager.h"@implementation MyAppManagerRCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(invokeCallback:(NSDictionary *)data) { //doSomething...}@endpackage me.tom.myapp;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;import com.facebook.react.bridge.ReadableMap;public class MyAppManager extends ReactContextBaseJavaModule { public MyAppManager(ReactApplicationContext reactContext) { super(reactContext);
} @Override
public String getName() { return "MyAppManager";
} @ReactMethod
public void invokeCallback(ReadableMap data) { //doSomething...
}
}上述实例中,我们在监听事件的处理方法中通过调用在native中定义的MyAppManager#invokeCallback方法来通知native端进行后续处理的方式实现了我们一开始的需求。但这样的实现个人认为存在以下几个方面的问题:
JavaScript端必须手动调用
MyAppManager.invokeCallback(...),啰嗦且容易忘记。Native发送事件的地方一般是在UIViewController、Activity或Fragment中,因此
MyAppManager还需要根据不用的参数将执行任务派发到相应真实的处理方法中,这里将充斥着大量的模版代码且易于出错。
针对上面的问题,个人简单的封装了一个库,上面的实例就可以简化为:
Native发送event到JavaScript并执行回调
#import "ZMReactEventEmitter.h"RCTBridge *bridge = ....
ZMReactEventEmitter *eventEmitter = [ZMReactEventEmitter new];
[eventEmitter sendEvent:bridge name:@"demo" params:@"Request from Native" callback:^(id data) { //doSomething...}];import me.tom.react.event.ReactEventEmitter;import me.tom.react.event.ReactEventEmitterCallbackHandler;
ReactContext context = ...;
ReactEventEmitter eventEmitter = new ReactEventEmitter();
eventEmitter.sendEvent(context, "demo", "Request from Native", new ReactEventEmitterCallbackHandler() { @Override
public void handler(ReadableMap data) { //doSomething...
}
});JavaScript监听事件并触发回调
import React from 'react';import ReactEventEmitter from 'rn-event-emitter-callback';class MyApp extends React.PureComponent {
componentWillMount() {
ReactEventEmitter.addListener('demo', (params, callback) => { //doSomething...
callback('Response from React Native');
})
}
componentWillUnmount() {
ReactEventEmitter.removeListener('demo');
}
}
作者:泪已无痕
链接:https://www.jianshu.com/p/e2f1b4c095e6
随时随地看视频