国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

React Native與Android 原生通信的方法

2019-10-22 18:11:56
字體:
來源:轉載
供稿:網友

我們用React Native 做混合開發的時候免不了要原生和React Native 進行通信交互,這篇文章就是分享原生模塊與JS傳遞數據的幾種方式。

總的步驟可以分為如下幾點:

  1. 在原生端定義Module類,繼承ReactContextBaseJavaModule,在Module類里,定義交互的方法.
  2. 定義Package類,繼承ReactPackage,將Module實例添加到集合.
  3. 在android繼承的ReactApplication,回調實現getPackages方法,將Package實例添加到getPackages下的集合。

如下是Mudule類的實例代碼,為了方便大家理解,我把代碼全部貼出來,在一一講解。

import android.support.annotation.Nullable;import android.widget.Toast;import com.facebook.react.bridge.Arguments;import com.facebook.react.bridge.Callback;import com.facebook.react.bridge.Promise;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;import com.facebook.react.bridge.WritableMap;import com.facebook.react.modules.core.DeviceEventManagerModule;import java.util.HashMap;import java.util.Map;public class ToastExample extends ReactContextBaseJavaModule{  private static final String LONG_TIME = "LONG";  private static final String SHORT_TIME = "SHORT";  private static final String MESSAGE = "MESSAGE";  public ToastExample(ReactApplicationContext reactContext) {    super(reactContext);  }  @Override  public String getName() {    return "ToastForAndroid";  }  @ReactMethod  public void getDataFromIntent(Callback callback){    try{      Activity currentActivity=getCurrentActivity();      String result =currentActivity.getIntent().getStringExtra("data");      if(TextUtils.isEmpty(result)){        callback.invoke("no_data");      }else{        callback.invoke(result);      }    }catch (Exception e){      callback.invoke("error");    }  }  @Override  public Map<String, Object> getConstants() {    //讓js那邊能夠使用這些常量    Map<String,Object> constants = new HashMap<>();    constants.put(LONG_TIME, Toast.LENGTH_LONG);    constants.put(SHORT_TIME,Toast.LENGTH_SHORT);    constants.put(MESSAGE,"getConstants");    return constants;  }  @ReactMethod  public void show(int duration){    Toast.makeText(getReactApplicationContext(),"message:"+duration,duration).show();  }  @ReactMethod  public void sendEvent(){    onScanningResult();  }  @ReactMethod  public void testAndroidCallbackMethod(String msg, Callback callback){    Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_LONG).show();    callback.invoke("abc");  }  @ReactMethod  public void textAndroidPromiseMethod(String msg, Promise promise){    Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show();    String result="謝漢杰";    promise.resolve(result);  }  public void onScanningResult(){    WritableMap params = Arguments.createMap();    params.putString("key", "myData");    sendEvent(getReactApplicationContext(),"EventName",params);  }  public static void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {    reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);  }  public void nativeCallRn(){    onScanningResult();  }  @Override  public boolean canOverrideExistingModule() {    return true;  }}

在上面的Module代碼中,getName()方法返回的名字是是在RN代碼里面是需要這個名字來調用該類的方法,而@ReactMethod注解下的方法是我們自定義方法,表明這個方法可以被rn調用.至于上面四種形式的方法等步驟走完詳解。

自定義ReactPackage 代碼如下:

import com.facebook.react.ReactPackage;import com.facebook.react.bridge.NativeModule;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.uimanager.ViewManager;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class ExampleReactNativePackage implements ReactPackage{  public ToastExample toastExample;  @Override  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {    List<NativeModule> modules = new ArrayList<>();    toastExample=new ToastExample(reactContext);    modules.add(toastExample);    return modules;  }  @Override  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {    return Collections.emptyList();  }}

這一步很簡單,就是把上面的ToastExample類加入NativeModule而已

接著第三步也很簡單,代碼如下

import android.app.Application;import com.facebook.react.ReactApplication;import com.facebook.react.ReactNativeHost;import com.facebook.react.ReactPackage;import com.facebook.react.shell.MainReactPackage;import java.util.Arrays;import java.util.List;public class MyApplication extends Application implements ReactApplication{  public static final ExampleReactNativePackage exampleReactNativePackage=new ExampleReactNativePackage();  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {    @Override    public boolean getUseDeveloperSupport() {      return BuildConfig.DEBUG;    }    @Override    protected List<ReactPackage> getPackages() {      return Arrays.<ReactPackage>asList(          new MainReactPackage(),          exampleReactNativePackage      );    }  };  @Override  public ReactNativeHost getReactNativeHost() {    return mReactNativeHost;  }}

這也不也只是把ExampleReactNativePackage添加進ReactPackage而已,也很簡單。

為此整個Android原生端已經完成編寫。接著就是編寫js端,下面也是js端的實例:(說句廢話,我一般喜歡貼全部代碼在一一講解,這樣比較連貫)

import React from 'react';import { AppRegistry, StyleSheet, Text, View, TouchableOpacity, ToastAndroid, NativeModules, DeviceEventEmitter} from 'react-native';export default class HelloWorld extends React.Component {  constructor(props){    super(props);    this.state={       text1:'ToastForAndroid',       text2:'testAndroidCallbackMethod',       text3:'textAndroidPromiseMethod',       text4:'DeviceEventEmitter',       text5:'getValue',       data:'no_data',    }  }  componentWillMount() {    DeviceEventEmitter.addListener('EventName', function (msg) {      console.log(msg);      let rest=NativeModules.ToastForAndroid.MESSAGE;      ToastAndroid.show("DeviceEventEmitter收到消息:" + "/n" + rest, ToastAndroid.SHORT)    });    NativeModules.ToastForAndroid.getDataFromIntent((result)=>{      this.setState({data:result});    });  }  render() {   return (     <View style={styles.container}>      <Text>{this.state.data}</Text>      <TouchableOpacity onPress={this._onPressButton.bind(this)}>         <Text style={styles.hello}>{this.state.text1}</Text>      </TouchableOpacity>      <TouchableOpacity onPress={this._onPressButton2.bind(this)}>         <Text style={styles.hello}>{this.state.text2}</Text>      </TouchableOpacity>      <TouchableOpacity onPress={this._onPressButton3.bind(this)}>         <Text style={styles.hello}>{this.state.text3}</Text>      </TouchableOpacity>      <TouchableOpacity onPress={this._onPressButton4.bind(this)}>         <Text style={styles.hello}>{this.state.text4}</Text>      </TouchableOpacity>      <TouchableOpacity onPress={this._onPressButton5.bind(this)}>         <Text style={styles.hello}>{this.state.text5}</Text>      </TouchableOpacity>     </View>    )  }  _onPressButton(){    NativeModules.ToastForAndroid.show(1000);  }  _onPressButton2(){    NativeModules.ToastForAndroid.testAndroidCallbackMethod("HelloJack",(result)=>{      this.setState({text:result});    });  }  _onPressButton3(){    NativeModules.ToastForAndroid.textAndroidPromiseMethod("abcx").then((result)=>{         this.setState({text3:result});       }).catch((error)=>{         this.setState({text:'error'});       })  }  _onPressButton4(){    NativeModules.ToastForAndroid.sendEvent();  }  _onPressButton5(){     ToastAndroid.show(NativeModules.ToastForAndroid.MESSAGE, ToastAndroid.SHORT)  }}  var styles = StyleSheet.create({   container: {    flex: 1,    justifyContent: 'center',    flexDirection: 'column',   },   hello: {    fontSize: 20,    textAlign: 'center',    margin: 10,   },  });AppRegistry.registerComponent('HelloWorlds', () => HelloWorld);

這就是整個js端的調用實例。在React Naitve層,RN端可通過 NativeModules.[module名].[方法名]來調起原生的方法,同時也可以通過RN端可通過 NativeModules.[module名].[參數名]的方式來獲取傳遞的參數,具體用法如上代碼。

而對于原生調用調用React Native里面的方法,我們可以用RCTDeviceEventEmitter的方式,這種方式就相當于我們Android中的廣播,具體對應的原生代碼如下:

MyApplication.exampleReactNativePackage.toastExample.nativeCallRn();

和上面的代碼也是連貫一起的。

最后總結交互的四種方式

第一種最簡單,如上面代碼的

@ReactMethod public void show(int duration){  Toast.makeText(getReactApplicationContext(),"message:"+duration,duration).show(); }

即用ReactMethod注解方法就可以調用原生了

Callback 回調方式,如上面代碼的

@ReactMethod public void testAndroidCallbackMethod(String msg, Callback callback){  Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_LONG).show();    callback.invoke("abc");}

對應的js代碼就是

_onPressButton2(){  NativeModules.ToastForAndroid.testAndroidCallbackMethod("HelloJack",(result)=>{      this.setState({text:result});  });}

即你傳入參數進行操作然后給你回調結果

3.Promise 回調方式類似的就是RxJava.可以通過鏈式將復雜代碼結構轉換為簡短易讀的代碼.,如上面代碼的

@ReactMethod  public void textAndroidPromiseMethod(String msg, Promise promise){    Toast.makeText(getReactApplicationContext(),msg,Toast.LENGTH_SHORT).show();    String result="謝漢杰";    promise.resolve(result);  }

對應的js代碼就是

_onPressButton3(){    NativeModules.ToastForAndroid.textAndroidPromiseMethod("abcx").then((result)=>{         this.setState({text3:result});       }).catch((error)=>{         this.setState({text:'error'});       })  }

JS端通過then接口來獲取Promise的數據,執行錯誤就返回error信息

通過事件方式:RCTDeviceEventEmitter,一般是native原生調用React Native 相當于廣播。對應上面代碼如下:

public static void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {    reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);  }

對應的js代碼就是

DeviceEventEmitter.addListener('EventName', function (msg) {      console.log(msg);      let rest=NativeModules.ToastForAndroid.MESSAGE;      ToastAndroid.show("DeviceEventEmitter收到消息:" + "/n" + rest, ToastAndroid.SHORT)  });

Native發送原生事件然后React Native 注冊監聽獲取信息。

在這里舉一個我們實戰的一個例子,就是啟動RN界面并且傳遞數據。怎么做呢,剛開始的初學者還是一下子反應不過來,起始也很簡單,充分運用我們上面的例子就行了,

首先原生啟動代碼

Intent intent=new Intent(MainActivity.this,HelloReactActivity.class);intent.putExtra("data","HelloJack");startActivity(intent);

最終要的是是在上面 的ToastExample類里加入

@ReactMethod  public void getDataFromIntent(Callback callback){    try{      Activity currentActivity=getCurrentActivity();      String result =currentActivity.getIntent().getStringExtra("data");      if(TextUtils.isEmpty(result)){        callback.invoke("no_data");      }else{        callback.invoke(result);      }    }catch (Exception e){      callback.invoke("error");    }  }

然后在RN端獲取即可

NativeModules.ToastForAndroid.getDataFromIntent((result)=>{  this.setState({data:result});});

同理其他情況請參考RN之Android:原生界面與React界面的相互調用及數據傳遞 ,這也是我的參考之一。

最后獻上大家最期待的源碼 https://github.com/jack921/ReactNativeParam 還有什么不明白就開源碼吧

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 卫辉市| 靖远县| 萝北县| 疏附县| 郑州市| 新巴尔虎右旗| 庐江县| 佛学| 巨野县| 湟源县| 通化县| 明溪县| 泗阳县| 二连浩特市| 开江县| 丰顺县| 武功县| 竹北市| 普格县| 水富县| 泸西县| 永福县| 伊吾县| 阳高县| 马山县| 景泰县| 德令哈市| 佳木斯市| 象州县| 象山县| 油尖旺区| 连南| 荣成市| 武安市| 卓尼县| 耿马| 延寿县| 铅山县| 鄯善县| 萨迦县| 介休市|