600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > React native和原生之间的通信

React native和原生之间的通信

时间:2020-04-18 14:37:07

相关推荐

React native和原生之间的通信

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

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

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

2)使用Promise来实现。

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

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

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

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

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

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

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

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

如下所示:

[java]view plaincopypublicclassMyModuleextendsReactContextBaseJavaModule{privateBluetoothAdaptermBluetoothAdapter=null;publicMyModule(ReactApplicationContextreactContext){super(reactContext);原生类1.MyContext=reactContext;}.......以下写被@ReactNative所标注的方法...............................................}

此时,reactContext将不会是null。也就不会报错。

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

[java]view plaincopyWritableMapevent=Arguments.createMap();sendEvent(MyContext,"EventName",event);

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

然后使用componentWillMount建立监听。

代码如下:

[javascript]view plaincopycomponentWillMount(){DeviceEventEmitter.addListener('EventName',function(){alert("sendsuccess");});}

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

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

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

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

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

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

代码如下:

ManiActivity.Java

[java]view plaincopypackagecom.ywq;importcom.facebook.react.ReactActivity;publicclassMainActivityextendsReactActivity{/***ReturnsthenameofthemaincomponentregisteredfromJavaScript.*Thisisusedtoschedulerenderingofthecomponent.*/@OverrideprotectedStringgetMainComponentName(){return"ywq";}}

ManiApplication.java

[java]view plaincopypackagecom.ywq;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;publicclassMainApplicationextendsApplicationimplementsReactApplication{privatefinalReactNativeHostmReactNativeHost=newReactNativeHost(this){@OverrideprotectedbooleangetUseDeveloperSupport(){returnBuildConfig.DEBUG;}@OverrideprotectedList<ReactPackage>getPackages(){returnArrays.<ReactPackage>asList(newMainReactPackage(),newMyPackage());}};@OverridepublicReactNativeHostgetReactNativeHost(){returnmReactNativeHost;}}

MyModule.java

[java]view plaincopypackagecom.ywq;importcom.facebook.react.bridge.ReactApplicationContext;importcom.facebook.react.bridge.ReactContextBaseJavaModule;importcom.facebook.react.bridge.ReactMethod;/***CreatedbyAdministratoron/10/30.*/publicclassMyModuleextendsReactContextBaseJavaModule{publicMyModule(ReactApplicationContextreactContext){super(reactContext);//给上下文对象赋值Test.myContext=reactContext;}@OverridepublicStringgetName(){return"MyModule";}@ReactMethodpublicvoidNativeMethod(){//调用Test类中的原生方法。newTest().fun();}}

MyPackage.java

[java]view plaincopypackagecom.ywq;importcom.facebook.react.ReactPackage;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;importjava.util.List;/***CreatedbyAdministratoron/10/30.*/publicclassMyPackageimplementsReactPackage{@OverridepublicList<NativeModule>createNativeModules(ReactApplicationContextreactContext){List<NativeModule>modules=newArrayList<>();modules.add(newMyModule(reactContext));returnmodules;}@OverridepublicList<Class<?extendsJavaScriptModule>>createJSModules(){returnCollections.emptyList();}@OverridepublicList<ViewManager>createViewManagers(ReactApplicationContextreactContext){returnCollections.emptyList();}}

Test.java

[java]view plaincopypackagecom.ywq;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;/***CreatedbyAdministratoron/10/30.*/publicclassTest{//定义上下文对象publicstaticReactContextmyContext;//定义发送事件的函数publicvoidsendEvent(ReactContextreactContext,StringeventName,@NullableWritableMapparams){System.out.println("reactContext="+reactContext);reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName,params);}publicvoidfun(){//在该方法中开启线程,并且延迟3秒,然后向JavaScript端发送事件。newThread(newRunnable(){@Overridepublicvoidrun(){try{Thread.sleep(3000);}catch(InterruptedExceptione){e.printStackTrace();}//发送事件,事件名为EventNameWritableMapet=Arguments.createMap();sendEvent(myContext,"EventName",et);}}).start();}}

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

[javascript]view plaincopy/***SampleReactNativeApp*/facebook/react-native*@flow*/importReact,{Component}from'react';import{AppRegistry,StyleSheet,Text,DeviceEventEmitter,NativeModules,View}from'react-native';exportdefaultclassywqextendsComponent{componentWillMount(){//监听事件名为EventName的事件DeviceEventEmitter.addListener('EventName',function(){alert("sendsuccess");});}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}</Text></View>);}callNative(){NativeModules.MyModule.NativeMethod();}}conststyles=StyleSheet.create({container:{flex:1,justifyContent:'center',alignItems:'center',backgroundColor:'#F5FCFF',},welcome:{fontSize:20,textAlign:'center',margin:10,},instructions:{textAlign:'center',color:'#333333',marginBottom:5,},});AppRegistry.registerComponent('ywq',()=>ywq);

运行结果如下所示:

点击之前:

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

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

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

[javascript]view plaincopy/***SampleReactNativeApp*/facebook/react-native*@flow*/importReact,{Component}from'react';import{AppRegistry,StyleSheet,Text,DeviceEventEmitter,NativeModules,View}from'react-native';exportdefaultclassywqextendsComponent{componentWillMount(){//监听事件名为EventName的事件DeviceEventEmitter.addListener('EventName',function(){this.showState();alert("sendsuccess");});}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}</Text></View>);}callNative(){NativeModules.MyModule.NativeMethod();}showState(){this.setState({content:'已经收到了原生模块发送来的事件'})}}conststyles=StyleSheet.create({container:{flex:1,justifyContent:'center',alignItems:'center',backgroundColor:'#F5FCFF',},welcome:{fontSize:20,textAlign:'center',margin:10,},instructions:{textAlign:'center',color:'#333333',marginBottom:5,},});AppRegistry.registerComponent('ywq',()=>ywq);

很明显:当收到事件时,改变一个文本框的内容,即更新UI。

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

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

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

修改UI代码如下:

[javascript]view plaincopy/***SampleReactNativeApp*/facebook/react-native*@flow*/importReact,{Component}from'react';import{AppRegistry,StyleSheet,Text,DeviceEventEmitter,NativeModules,View}from'react-native';exportdefaultclassywqextendsComponent{componentWillMount(){//监听事件名为EventName的事件DeviceEventEmitter.addListener('EventName',()=>{this.showState();alert("sendsuccess");});}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}</Text></View>);}callNative(){NativeModules.MyModule.NativeMethod();}showState(){this.setState({content:'已经收到了原生模块发送来的事件'})}}conststyles=StyleSheet.create({container:{flex:1,justifyContent:'center',alignItems:'center',backgroundColor:'#F5FCFF',},welcome:{fontSize:20,textAlign:'center',margin:10,},instructions:{textAlign:'center',color:'#333333',marginBottom:5,},});AppRegistry.registerComponent('ywq',()=>ywq); 运行之后,界面刷新了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。