rn+与android+交互,React native 与Android原生交互方式(一)

前言##

最近在做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资源文件的代码:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="com.example.wangfang.rnproject.MainActivity">

android:id="@+id/btn_go_react"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="原生界面跳转React界面"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintLeft_toLeftOf="parent"

app:layout_constraintRight_toRightOf="parent"

app:layout_constraintTop_toTopOf="parent" />

还有清单文件 这里就不贴代码了,相信做过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”事件的监听。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值