RN中文网关于原生模块(Android)的介绍可以看到,RN前端与原生模块之
间通信,主要有三种方法:
1)使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript。
2)使用Promise来实现。
3)原生模块向JavaScript发送事件。
关于使用回调,这是最简单的一种通信,这里可以看看官网的实现,今天要讲的是滴三种由原生模块向JavaScript发送事件。
(1)首先,你需要定义一个发送事件的方法。如下所示:
- 这可以通过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赋值。
如下所示:
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建立监听。
代码如下:
componentWillMount(){
- DeviceEventEmitter.addListener('EventName',function(){
- alert("sendsuccess");
- });
- }
注意:该监听必须放在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代码如下:
- *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的事件
- DeviceEventEmitter.addListener('EventName',()=>{
- this.showState();
- alert("sendsuccess");
- });
- }
- constructor(props){
- super(props);
- this.state={
- content:'这个是预定的接受信息',248); line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; list-style-position: outside !important;">}
- 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();
- showState()
- {
- this.setState({content:'已经收到了原生模块发送来的事件'})
- conststyles=StyleSheet.create({
- container:{
- 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:{
- 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:{
- 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;">});
- AppRegistry.registerComponent('ywq',()=>ywq);
运行之后,界面刷新了。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|