React Native event支持callback

作者: 泪已无痕 | 来源:发表于2018-10-03 09:56 被阅读37次

有时我们从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 MyAppManager

RCT_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://github.com/nanjingboy/React-Native-Event ^ _ ^

相关文章

网友评论

    本文标题:React Native event支持callback

    本文链接:https://www.haomeiwen.com/subject/hdrzoftx.html