React native與原生應用(二)--JS與原生應用間傳遞數據

參考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
  1. 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;
    }
}
  1. 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 { 
// 
}
})
  1. 原生模塊向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, }); 
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容