这里所说的通信,指的是参数互传,以及react-native调用native的方法。(ps: native 调用react-native中的方法?没有必要吧,毕竟android本地端比react-native多活那么多年,react-native有的,android端都能实现。)
- 首先创建一个类,继承自ReactContextBaseJavaModule,这个类是以后react-native调用native方法的总管理类:
public class MyIntentModule extends ReactContextBaseJavaModule {
private ReactApplicationContext mContext; //用来管理ReactContextBaseJavaModule 的一个全局上下文
public static final String MODULE_NAME = "TTRNBridgeModule"; //别名
public static final String EVENT_NAME_LOGIN_FOR_REFRESH = "refreshView";//登录监听码
public MyIntentModule(ReactApplicationContext reactContext) {
super(reactContext);
this.mContext = reactContext;
}
@Override
public String getName() { //必须重写
return MODULE_NAME;
}
/**
* RN调用Native的方法
* @param phone
*/
@ReactMethod
public void rnCallNative(String phone) {//该方法是自定的,方法头部必须添加@ReactMethod注解,RN才能找得到
// 跳转到打电话界面
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + phone));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 跳转需要添加flag, 否则报错
mContext.startActivity(intent);
}
/**
* RN跳转到android页面操作
*/
@ReactMethod
public void rnCallNativeToShelf(){
Intent intent = new Intent(mContext,BookShelfActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
/**
* Native调用RN 监听的方式
* 从RN端 注册一个监听,然后在本地发送一个监听
* @param msg
*/
public void nativeCallRnLoginForRefresh(final int msg) { // 0 -- 登录成功 1 -- 登录失败
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(EVENT_NAME_LOGIN_FOR_REFRESH,msg);
}
}
RN操作
- 创建类实现ReactPackage:
public class MyReactPackage implements ReactPackage {
public MyIntentModule mModule; //上面创建的ReactContextBaseJavaModule
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
mModule=new MyIntentModule(reactContext);
modules.add(mModule);
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
这里写法比较固定,一般没有什么大的变化。
- ** 最后一步就是在你的Application当中,作一下操作:**
public class BaseApp extends Application implements ReactApplication {
public static final MyReactPackage mCommPackage = new MyReactPackage();//上面创建的ReactPackage
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return true;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
mCommPackage
);
}
};
@Override
public void onCreate() {
super.onCreate();
}
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
是不是很简洁,不得不说RN这点做得很好,完全是0污染。
以上都是准备工作 ,下面我们就来解决问题
1.下面,我们先来RN调用native方法吧,直接在你的RN代码中调用上面在ReactContextBaseJavaModule 已经用@ReactMethod声明了的方法,调用方法如下:
import React, {Component} from 'react';
import {
...
NativeModules,
...
} from 'react-native';
export default class Xxxx extends Component {
rnCallNative = ()=>{
NativeModules.TTRNBridgeModule.rnCallNativeToShelf();
}
}
TTRNBridgeModule看起来是不是好眼熟,没错,就是上面创建的ReactContextBaseJavaModule 的别名。
2.native 向RN传参,直接在关联的Activity中重写方法createReactActivityDelegate并传参:
public class CollectionSearchRNActivity extends ReactActivity {
public static final String MAIN_COMPONENTNAME = "collectionSearch";
@Override
protected String getMainComponentName() {
return MAIN_COMPONENTNAME;
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
PreLoadReactActivityDelegate preLoadReactActivityDelegate =new PreLoadReactActivityDelegate(this, this.getMainComponentName());
Bundle launchOptions = new Bundle();
launchOptions.putString("orgGid", MyIntentModule.ORGGID);
launchOptions.putString("passportGid",MyIntentModule.PASSPORTGID);
launchOptions.putString("authorizationCode",MyIntentModule.AUTHORIZATIONCODE);
preLoadReactActivityDelegate.setBundle(launchOptions);
return preLoadReactActivityDelegate;
}
}
还有一种做法,RN在需要的时候,让native向RN传参,callback形式:
@ReactMethod
public void rnInvokeisLoginCallBack(Callback callback){
if (UserLoginActivity.isRNLogined(mContext.getCurrentActivity(),true,REQUEST_CODE)){
String passport = SPUtils.get(DefineParamsKey.PASSPORT_GID,"").toString();
String orgGid = SPUtils.get(DefineParamsKey.ORG_GID,"").toString();
callback.invoke(orgGid,passport);
}
}
那么RN怎么获取呢?如下:
//TTRNBridgeModule 是别名,rnInvokeisLoginCallBack是函数名,NativeModules为依赖
NativeModules.TTRNBridgeModule.rnInvokeisLoginCallBack((orgGid, passportGid) => {
if (orgGid == "" || passportGid == null) {//未登录
return;
} else {
global.orgGid = orgGid;//global全局变量记录参数
global.passportGid = passportGid;
callback();//得到数据后可以调用该方法做相关操作
}
});
RN这里也是很简单很棒的设计。
3.RN向native传参,这个很简单了吧,不过好多人刚开始可能并没有想到,RN既然能够调用native方法,那么在方法里面放一个参数,又有什么不行的呢,不过传递对象过来的时候,通常传json字符串,然后自己在解析一下就行了。上面已经讲过RN调用native方法了,实际上传参也可以一并解决,不懂的自己去面壁思过~~~
4.最后一个就是native调用RN的方法了,目前native并不能直接调用RN的方法,而是通过native发送监听的方式,然后RN端接受到监听后,操作相应的方法,这个可以应用到登录的后需要更新RN视图的某些场景。
先看RN监听代码:
import React, {
DeviceEventEmitter,
NativeModules,
Platform
}from 'react-native';
export default class EventManager{
_subscriber = null; //监听者
/**
* @param eventType 监听的名称,用来区分监听,String类型
* @param callback 监听的回调,需要监听的方法
*/
init = (eventType,callback) =>{
this._subscriber = DeviceEventEmitter.addListener(eventType,(msg) =>{//msg,监听发过来的参数
if(msg == 0){
return ;
}
callback();
});
}
/**
* 销毁监听
*/
destroy=()=>{
if (this._subscriber != null) {
this._subscriber.remove();
}
}
}
以上是我封装的DeviceEventEmitter监听类的代码,下面看RN调用过程:
import React, {Component} from 'react';
import {
NativeModules,
DeviceEventEmitter,
} from 'react-native';
import EventManager from '../../util/event_manager';
export default class BookDetails extends Component {
constructor(props) {
super(props);
this.eventManager = new EventManager();//创建
this.eventManager.init('refreshView', this.getBookdetail);//注册
}
getBookdetail = ()=>{
//相关业务操作
}
//销毁
componentWillUnmount() {
this.eventManager.destroy();
}
}
native 发送监听的代码,在需要发送监听的地方使用
/**
* Native调用RN的方法 通过监听的方式
* 该方法是登录都发送的一个监听
* @param msg
*/
public void nativeCallRnLoginForRefresh(final int msg) { // 1 -- 登录成功 0 -- 登录失败
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("refreshView",msg);
}
nativeCallRnLoginForRefresh当android本地调用该方法,就会发送一个监听消息,RN接受到消息后,执行对应的方法,从而实现了native调用RN的方法。
好了,今天的共享就写到这里了,不明白的可以踊跃发言,相互学习。