参考react native中文网“原生模块(Android)” http://reactnative.cn/docs/0.48/native-modules-android.html#content,JS端与原生模块之间通信,主要有三种方法:
(1)使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript。
(2)使用Promise来实现。
(3)原生模块向JavaScript发送事件。
一、添加两个必要类
在使用这三种通信方法之前,在原生应用上需要实现三个类来与JS端进行交互:
- new ReactPackages类
在上一篇中,集成到现有原生应用中创建了一个类
ReactNativeInAndroidActivity extends ReactActivity implements DefaultHardwareBackBtnHand
在onCreate时,创建了一个ReactInstanceManager,并需要加入一个我们定义的一个ReactPackages
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setCurrentActivity(this)
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("currentDetail")
.addPackage(new MainReactPackage())
.addPackage(new AndroidNativePackage())//我们自己ReactPackages
.setUseDeveloperSupport(true)
.setInitialLifecycleState(LifecycleState.RESUMED)
.setDefaultHardwareBackBtnHandler(this)
.build();
new ReactPackages的实现可参考http://blog.csdn.net/qq_25827845/article/details/52963594,有一个简单的小例子来介绍用法。
在这个类中最关键的函数就是createNativeModules,
在该函数中我们需要new一个ReactContextBaseJavaModule类
public class AndroidNativePackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new CurrentModule(reactContext));
return modules;
}
}
- new ReactContextBaseJavaModule类
public class CurrentModule extends ReactContextBaseJavaModule
在这个类中有两个重要的函数:
a.
public CurrentModule(ReactApplicationContext reactContext) {
super(reactContext);
//要把上下文传递给ReactActivity类即ReactNativeInAndroidActivity,否则ReactNativeInAndroidActivity获得不了上下文
ReactNativeInAndroidActivity.mReactContext = reactContext;
}
b.
@Override
public String getName() {
//返回的这个字符串在JavaScript端标记这个模块,在JS端可以通过NativeModules.CurrentDetailModuleg访问到这个模块
return "CurrentDetailModule";
}
c. JS端通过上面的方法可以访问到CurrentModule这个类了,具体调用那个功能函数就需要使用下面这种方法
@ReactMethod //需要使用注解@ReactMethod。方法的返回类型必须为void
public void function() {
处理逻辑
}
JS可以通过NativeModules.CurrentDetailModule.function来访问这个函数
二、RN前端与原生模块之间通信
1、回调函数Callback,它提供了一个函数来把返回值传回给JavaScript
原生应用:
@ReactMethod
public void getLoginState(Callback callback)
{
try {
WritableMap map = Arguments.createMap();
map.putString("isLogin", "0");
callback.invoke(map);//把map传回给JS
} catch (IllegalViewOperationException e) {
Logger.i("React-Native:getLoginState"));
}
}
JS:
//可以访问到原生应用的CurrentDetailModule类
var bridge = NativeModules.CurrentDetailModule;
//访问CurrentDetailModule类中getLoginState函数,把原生传给JS的map赋值到properties
bridge.getLoginState((properties) => {
//从properties中取得key对应的value的值进行判断
if (properties["isLogin"] == '0') {
bridge.gotoLogin();
} else {
//
}
})
- 原生模块向JavaScript发送事件
原生模块可以在没有被调用的情况下往JavaScript发送事件通知。最简单的办法就是通过RCTDeviceEventEmitter,这可以通过ReactContext来获得对应的引用
原生应用:
@ReactMethod
public void sendDataToJs() {
WritableMap params = Arguments.createMap();
params.putString("SendData", "1234");//"SendData"是key值,通过它获得value值
//"eventName"是JS端监听的事件的名称
mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("eventName", params);
}
JS:
componentWillMount() {//JS组件还没有开始渲染时
this.callNative.bind(this);
//注册监听事件,监听事件名称为'eventName',监听处理函数
onScanningResult
DeviceEventEmitter.addListener('eventName', this.onScanningResult);
}
onScanningResult = (e) => { //e是从原生应用传过来的数据
//通过e.SendData获取key为SendData的value值
this.setState({ money: e.SendData, });
}