參考react native中文網“原生模塊(Android)” http://reactnative.cn/docs/0.48/native-modules-android.html#content,JS端與原生模塊之間通信,主要有三種方法:
(1)使用回調函數Callback,它提供了一個函數來把返回值傳回給JavaScript。
(2)使用Promise來實現。
(3)原生模塊向JavaScript發送事件。
一、添加兩個必要類
在使用這三種通信方法之前,在原生應用上需要實現三個類來與JS端進行交互:
Paste_Image.png
- 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, });
}