前言##
最近在做React Native开发的时候避免不了的需要原生模块和JS之间进行交互,其实RN和原生的通信大致分为两种情况;一种是Android主动向RN端发送事件和数据,另外一种是RN端被动向Android询问获取事件和数据,接下来的几篇文章将向大家分享原生模块向JS交互的几种方式。
1、发送事件的方式
2、callback方式
3、Promise方式
由于篇幅原因本文只对发送事件的方式进行详细介绍
发送事件的方式
使用了React Native的RCTDeviceEventEmitter,通过消息机制来实现,原生可以向JS传递事件而不需要直接的调用,就像我们android中的广播。
下面通就像大家暂时通过RCTDeviceEventEmitter来向JS传递事件。
原生模块中(Android端):
首先定义Module类:MyModule.java
public class MyModule extends ReactContextBaseJavaModule {
private final String TAG = MyModule.class.getName();
public MyModule(ReactApplicationContext reactContext) {
super(reactContext);
//给上下文对象赋值
Test.mContext = reactContext;
}
//不能用return tag 来实现 不然不能调用方法...原因不理解
@Override
public String getName() {
return "MyModule";
}
@ReactMethod
public void callNativeBySend(){
//调用Test类中的原生方法。
Log.e("wangfang","called send");
new Test().fun();
}
}
发送事件的代码在Test类中,
Test.java代码段如下:
public class Test {
public static ReactContext mContext;
public void fun()
{
//在该方法中开启线程,并且延迟3秒,然后向JavaScript端发送事件。
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//发送事件,事件名为EventName
WritableMap et= Arguments.createMap();
sendEvent(mContext,"EventName",et);
}
}).start();
}
//定义发送事件的函数
public void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params)
{
System.out.println("reactContext="+reactContext);
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName,params);//原生调Rn
}
}
从上述代码可以看到,原生向JS模块发送了一个名为“EventName”的事件,并携带了"et"作为参数,那大家肯定会问JS中如何接收事件并进行处理呢,别急。。。。
先把原生的代码说完,得把模块添加到包中
MyPackage代码如下:
public class MyPackage implements ReactPackage {
@Override
public List createNativeModules(ReactApplicationContext reactContext) {
List modules = new ArrayList<>();
modules.add(new MyModule(reactContext));
return modules;
}
@Override
public List> createJSModules() {
return Collections.emptyList();
}
@Override
public List createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
接着RN依附的Activity代码如下:
public class RnAndroidCommuActivity extends ReactActivity{
@Override
public String getMainComponentName() {
return "testNative";
}
}
原生的Activity的代码:
public class NativeActivity extends Activity {
private Button btnGoReact;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnGoReact = (Button)this.findViewById(R.id.btn_go_react);
btnGoReact.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(NativeActivity.this,RnAndroidCommuActivity.class);
intent.putExtra("result","native go to react");
startActivity(intent);
}
});
}
activity_main资源文件的代码:
还有清单文件 这里就不贴代码了,相信做过Android的项目都知道咋写吧。。。
RN端的代码:
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
DeviceEventEmitter,
NativeModules,
View,
TextInput
} from 'react-native';
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
DeviceEventEmitter,
NativeModules,
View,
TextInput
} from 'react-native';
export class RnAndroidCommunication extends React.Component{
componentWillMount(){
DeviceEventEmitter.addListener("EventName",()=>{
this.showState();
alert("send event success");
});
}
constructor(props){
super(props);
this.state={
content:"这是个预定的接受消息"
}
}
render(){
return (
当你点我的时候会调用原生方法,原生方法延迟3s后会向前端发送事件。
前端一直在监听该事件,如果收到,则给出alert提示! send 方式
{this.state.content}
);
}
callNative(){
console.log(" js called by send");
NativeModules.MyModule.callNativeBySend();
}
showState(){
this.setState({content:"已经收到了原生模块发送来的事件,send event 方式"});
}
}
const myStyles = 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('testNative', () => RnAndroidCommunication);
在JS中通过 DeviceEventEmitter 注册监听了名为“”的事件,当原生模块发出名为“EventName”的事件后,绑定在该事件上的 EventName = () 会被回调。 然后通过就可获得事件所携带的数据,并执行回调函数,进行页面显示灯。
心得:如果在JS中有多处注册了 EventName 事件,那么当原生模块发出事件后,这些地方会同时收到该事件。不过大家也可以通过 DeviceEventEmitter.removeListener('onScanningResult',this.onScanningResult) 来移除对名为“EventName”事件的监听。
下一篇:React native 与Android原生交互方式(二)