为了账号安全,请及时绑定邮箱和手机立即绑定

React Native event支持callback

2018.10.28 12:36 918浏览

有时我们从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...}@end
package 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端进行后续处理的方式实现了我们一开始的需求。但这样的实现个人认为存在以下几个方面的问题:

  1. JavaScript端必须手动调用MyAppManager.invokeCallback(...),啰嗦且容易忘记。

  2. 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


点击查看更多内容
0人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消