加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

React native和原生之间的通信

发布时间:2020-12-15 08:19:04 所属栏目:百科 来源:网络整理
导读:RN中文网关于原生模块(Android)的介绍可以看到,RN前端与原生模块之 间通信,主要有三种方法: 1)使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript。 2)使用Promise来实现。 3)原生模块向JavaScript发送事件。 关于使用回调,这是最

RN中文网关于原生模块(Android)的介绍可以看到,RN前端与原生模块之

间通信,主要有三种方法:

1)使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript。

2)使用Promise来实现。

3)原生模块向JavaScript发送事件。

关于使用回调,这是最简单的一种通信,这里可以看看官网的实现,今天要讲的是滴三种由原生模块向JavaScript发送事件。

(1)首先,你需要定义一个发送事件的方法。如下所示:

[java]view plaincopy
  1. /*原生模块可以在没有被调用的情况下往JavaScript发送事件通知。
  2. 最简单的办法就是通过RCTDeviceEventEmitter,
  3. 这可以通过ReactContext来获得对应的引用,像这样:*/
  4. publicstaticvoidsendEvent(ReactContextreactContext,StringeventName,@NullableWritableMapparamss)
  5. {
  6. System.out.println("reactContext="+reactContext);
  7. reactContext
  8. .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
  9. .emit(eventName,paramss);
  10. }

其中方法名可以任意,但是参数不可改变。该方法可以放在你要复用的原生类中(即为原生类1)。

需要注意的是,由于版本问题,该函数中的参数reactContext有可能为null,此时会报NullPointException的错误。所以我们需要手动给reactContext赋值,见步骤2.

(2)我们在原生类1中,定义变量public static ReactContext MyContext;

然后在我们自定义的继承至ReactContextBaseJavaModule的类中给reactContext赋值。

如下所示:

copy
classMyModuleextendsReactContextBaseJavaModule{
  • privateBluetoothAdaptermBluetoothAdapter=null;
  • publicMyModule(ReactApplicationContextreactContext){
  • super(reactContext);
  • 原生类1.MyContext=reactContext;
  • }
  • .......以下写被@ReactNative所标注的方法
  • ............................
  • ...................
  • }
  • 此时,reactContext将不会是null。也就不会报错。

    (3)在某个原生函数中向JavaScript发送事件。如下所示:

    copy
    WritableMapevent=Arguments.createMap();
  • sendEvent(MyContext,"EventName",event);

  • (4)在RN前端监听事件。首先导入DeviceEventEmitter,即import{ DeviceEventEmitter } from 'react-native'

    然后使用componentWillMount建立监听。

    代码如下:

    [javascript]copy
      componentWillMount(){
    1. DeviceEventEmitter.addListener('EventName',function(){
    2. alert("sendsuccess");
    3. });
    4. }

    注意:该监听必须放在class里边,和render、const对齐。

    下边展示一个完整Demo,Demo功能如下:

    (1)JavaScript端在监听一个事件。

    (2)点击前端某行文字,调用原生方法。

    (3)在原生方法中,延迟3s后向前端发送对应事件。

    (4)前端接收到事件后,给出alert提示。

    代码如下:

    ManiActivity.Java

    copy
    packagecom.ywq;
  • importcom.facebook.react.ReactActivity;
  • classMainActivityextendsReactActivity{
  • /**
  • *ReturnsthenameofthemaincomponentregisteredfromJavaScript.
  • *Thisisusedtoschedulerenderingofthecomponent.
  • */
  • @Override
  • protectedStringgetMainComponentName(){
  • return"ywq";
  • }

  • ManiApplication.java

    copy
    importandroid.app.Application;
  • importandroid.util.Log;
  • importcom.facebook.react.ReactApplication;
  • importcom.facebook.react.ReactInstanceManager;
  • importcom.facebook.react.ReactNativeHost;
  • importcom.facebook.react.ReactPackage;
  • importcom.facebook.react.shell.MainReactPackage;
  • importjava.util.Arrays;
  • importjava.util.List;
  • classMainApplicationextendsApplicationimplementsReactApplication{
  • privatefinalReactNativeHostmReactNativeHost=newReactNativeHost(this){
  • @Override
  • protectedbooleangetUseDeveloperSupport(){
  • returnBuildConfig.DEBUG;
  • }
  • protectedList<ReactPackage>getPackages(){
  • returnArrays.<ReactPackage>asList(
  • newMainReactPackage(),
  • newMyPackage()
  • );
  • };
  • publicReactNativeHostgetReactNativeHost(){
  • returnmReactNativeHost;
  • }

  • MyModule.java

    copy
    importcom.facebook.react.bridge.ReactApplicationContext;
  • importcom.facebook.react.bridge.ReactContextBaseJavaModule;
  • importcom.facebook.react.bridge.ReactMethod;
  • *CreatedbyAdministratoron2016/10/30.
  • */
  • publicMyModule(ReactApplicationContextreactContext){
  • //给上下文对象赋值
  • Test.myContext=reactContext;
  • publicStringgetName(){
  • return"MyModule";
  • @ReactMethod
  • voidNativeMethod()
  • {
  • //调用Test类中的原生方法。
  • newTest().fun();
  • }

  • MyPackage.java

    copy
    importcom.facebook.react.bridge.JavaScriptModule;
  • importcom.facebook.react.bridge.NativeModule;
  • importcom.facebook.react.bridge.ReactApplicationContext;
  • importcom.facebook.react.uimanager.ViewManager;
  • importjava.util.ArrayList;
  • importjava.util.Collections;
  • classMyPackageimplementsReactPackage{
  • publicList<NativeModule>createNativeModules(ReactApplicationContextreactContext){
  • List<NativeModule>modules=newArrayList<>();
  • modules.add(newMyModule(reactContext));
  • returnmodules;
  • publicList<Class<?extendsJavaScriptModule>>createJSModules(){
  • returnCollections.emptyList();
  • publicList<ViewManager>createViewManagers(ReactApplicationContextreactContext){
  • returnCollections.emptyList();
  • }

  • Test.java

    copy
    importandroid.provider.Settings;
  • importandroid.support.annotation.Nullable;
  • importcom.facebook.react.bridge.Arguments;
  • importcom.facebook.react.bridge.ReactContext;
  • importcom.facebook.react.bridge.WritableMap;
  • importcom.facebook.react.modules.core.DeviceEventManagerModule;
  • classTest{
  • //定义上下文对象
  • staticReactContextmyContext;
  • //定义发送事件的函数
  • @NullableWritableMapparams)
  • System.out.println("reactContext="+reactContext);
  • reactContext
  • .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
  • .emit(eventName,params);
  • voidfun()
  • //在该方法中开启线程,并且延迟3秒,然后向JavaScript端发送事件。
  • newThread(newRunnable(){
  • voidrun(){
  • try{
  • Thread.sleep(3000);
  • }catch(InterruptedExceptione){
  • e.printStackTrace();
  • //发送事件,事件名为EventName
  • WritableMapet=Arguments.createMap();
  • sendEvent(myContext,et);
  • }).start();
  • }

  • 前端index.android.js代码如下:

    copy
    *SampleReactNativeApp
  • *https://github.com/facebook/react-native
  • *@flow
  • importReact,{Component}from'react';
  • import{
  • AppRegistry,
  • StyleSheet,
  • Text,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">DeviceEventEmitter,108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">NativeModules,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">View
  • }from'react-native';
  • exportdefaultclassywqextendsComponent{
  • componentWillMount(){
  • //监听事件名为EventName的事件
  • });
  • constructor(props){
  • super(props);
  • this.state={
  • content:'这个是预定的接受信息',
  • render(){
  • return(
  • <Viewstyle={styles.container}>
  • <Textstyle={styles.welcome}
  • onPress={this.callNative.bind(this)}
  • >
  • 当你点我的时候会调用原生方法,原生方法延迟3s后会向前端发送事件。
  • 前端一直在监听该事件,如果收到,则给出alert提示!
  • </Text>
  • <Textstyle={styles.welcome}>
  • {this.state.content}
  • </View>
  • callNative()
  • NativeModules.MyModule.NativeMethod();
  • conststyles=StyleSheet.create({
  • container:{
  • flex:1,108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">justifyContent:'center',248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">alignItems:'center',108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">backgroundColor:'#F5FCFF',248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">},108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">welcome:{
  • fontSize:20,108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">textAlign:'center',248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">margin:10,108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">},248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">instructions:{
  • color:'#333333',108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">marginBottom:5,108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">AppRegistry.registerComponent('ywq',()=>ywq);

  • 运行结果如下所示:

    点击之前:


    调用原生方法并且等待3s后:


    再说一个值得注意的地方,一般我们在接收到原生模块主动发来的事件时,都会进行一些操作,如更新UI,而不仅仅是弹出alert 。

    例如我们需要更新UI,代码如下:

    copy
    this.showState();
  • showState()
  • this.setState({content:'已经收到了原生模块发送来的事件'})
  • 很明显:当收到事件时,改变一个文本框的内容,即更新UI。

    运行结果如下,说明在此function中不能使用this,也就是我们并不能更新UI。


    那我们能做到在接收到事件后更新UI等后续操作吗?

    使用胖箭头函数(Fat arrow functions)

    修改UI代码如下:

    [javascript] view plain copy
      /**
    1. *SampleReactNativeApp
    2. *https://github.com/facebook/react-native
    3. *@flow
    4. */
    5. importReact,{Component}from'react';
    6. import{
    7. AppRegistry,
    8. StyleSheet,
    9. Text,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">DeviceEventEmitter,108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">NativeModules,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">View
    10. }from'react-native';
    11. exportdefaultclassywqextendsComponent{
    12. componentWillMount(){
    13. //监听事件名为EventName的事件
    14. DeviceEventEmitter.addListener('EventName',()=>{
    15. this.showState();
    16. alert("sendsuccess");
    17. });
    18. }
    19. constructor(props){
    20. super(props);
    21. this.state={
    22. content:'这个是预定的接受信息',248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">}
    23. render(){
    24. return(
    25. <Viewstyle={styles.container}>
    26. <Textstyle={styles.welcome}
    27. onPress={this.callNative.bind(this)}
    28. >
    29. 当你点我的时候会调用原生方法,原生方法延迟3s后会向前端发送事件。
    30. 前端一直在监听该事件,如果收到,则给出alert提示!
    31. </Text>
    32. <Textstyle={styles.welcome}>
    33. {this.state.content}
    34. </View>
    35. );
    36. callNative()
    37. {
    38. NativeModules.MyModule.NativeMethod();
    39. showState()
    40. {
    41. this.setState({content:'已经收到了原生模块发送来的事件'})
    42. conststyles=StyleSheet.create({
    43. container:{
    44. flex:1,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">justifyContent:'center',108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">alignItems:'center',248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">backgroundColor:'#F5FCFF',108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">},248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">welcome:{
    45. fontSize:20,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">textAlign:'center',108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">margin:10,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">},108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">instructions:{
    46. color:'#333333',248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">marginBottom:5,248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">});
    47. AppRegistry.registerComponent('ywq',()=>ywq);
    运行之后,界面刷新了。

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    • 推荐文章
        热点阅读