參考react native中文網(wǎng)“原生模塊(Android)” http://reactnative.cn/docs/0.48/native-modules-android.html#content置鼻,JS端與原生模塊之間通信架曹,主要有三種方法:
(1)使用回調(diào)函數(shù)Callback种冬,它提供了一個(gè)函數(shù)來(lái)把返回值傳回給JavaScript敷钾。
(2)使用Promise來(lái)實(shí)現(xiàn)。
(3)原生模塊向JavaScript發(fā)送事件愈犹。
一键科、添加兩個(gè)必要類
在使用這三種通信方法之前,在原生應(yīng)用上需要實(shí)現(xiàn)三個(gè)類來(lái)與JS端進(jìn)行交互:
- new ReactPackages類
在上一篇中漩怎,集成到現(xiàn)有原生應(yīng)用中創(chuàng)建了一個(gè)類
ReactNativeInAndroidActivity extends ReactActivity implements DefaultHardwareBackBtnHand
在onCreate時(shí)勋颖,創(chuàng)建了一個(gè)ReactInstanceManager,并需要加入一個(gè)我們定義的一個(gè)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的實(shí)現(xiàn)可參考http://blog.csdn.net/qq_25827845/article/details/52963594勋锤,有一個(gè)簡(jiǎn)單的小例子來(lái)介紹用法饭玲。
在這個(gè)類中最關(guān)鍵的函數(shù)就是createNativeModules,
在該函數(shù)中我們需要new一個(gè)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
在這個(gè)類中有兩個(gè)重要的函數(shù):
a.
public CurrentModule(ReactApplicationContext reactContext) {
super(reactContext);
//要把上下文傳遞給ReactActivity類即ReactNativeInAndroidActivity叁执,否則ReactNativeInAndroidActivity獲得不了上下文
ReactNativeInAndroidActivity.mReactContext = reactContext;
}
b.
@Override
public String getName() {
//返回的這個(gè)字符串在JavaScript端標(biāo)記這個(gè)模塊茄厘,在JS端可以通過(guò)NativeModules.CurrentDetailModuleg訪問到這個(gè)模塊
return "CurrentDetailModule";
}
c. JS端通過(guò)上面的方法可以訪問到CurrentModule這個(gè)類了,具體調(diào)用那個(gè)功能函數(shù)就需要使用下面這種方法
@ReactMethod //需要使用注解@ReactMethod谈宛。方法的返回類型必須為void
public void function() {
處理邏輯
}
JS可以通過(guò)NativeModules.CurrentDetailModule.function來(lái)訪問這個(gè)函數(shù)
二次哈、RN前端與原生模塊之間通信
1、回調(diào)函數(shù)Callback吆录,它提供了一個(gè)函數(shù)來(lái)把返回值傳回給JavaScript
原生應(yīng)用:
@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:
//可以訪問到原生應(yīng)用的CurrentDetailModule類
var bridge = NativeModules.CurrentDetailModule;
//訪問CurrentDetailModule類中g(shù)etLoginState函數(shù)窑滞,把原生傳給JS的map賦值到properties
bridge.getLoginState((properties) => {
//從properties中取得key對(duì)應(yīng)的value的值進(jìn)行判斷
if (properties["isLogin"] == '0') {
bridge.gotoLogin();
} else {
//
}
})
- 原生模塊向JavaScript發(fā)送事件
原生模塊可以在沒有被調(diào)用的情況下往JavaScript發(fā)送事件通知。最簡(jiǎn)單的辦法就是通過(guò)RCTDeviceEventEmitter恢筝,這可以通過(guò)ReactContext來(lái)獲得對(duì)應(yīng)的引用
原生應(yīng)用:
@ReactMethod
public void sendDataToJs() {
WritableMap params = Arguments.createMap();
params.putString("SendData", "1234");//"SendData"是key值哀卫,通過(guò)它獲得value值
//"eventName"是JS端監(jiān)聽的事件的名稱
mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("eventName", params);
}
JS:
componentWillMount() {//JS組件還沒有開始渲染時(shí)
this.callNative.bind(this);
//注冊(cè)監(jiān)聽事件,監(jiān)聽事件名稱為'eventName'撬槽,監(jiān)聽處理函數(shù)
onScanningResult
DeviceEventEmitter.addListener('eventName', this.onScanningResult);
}
onScanningResult = (e) => { //e是從原生應(yīng)用傳過(guò)來(lái)的數(shù)據(jù)
//通過(guò)e.SendData獲取key為SendData的value值
this.setState({ money: e.SendData, });
}