iOS篇
RN调用iOS
iOS准备工作:
首先要创建一个Object类PushNative(类名随意,这个是桥接文件),
PushNative.h中导入RCTBridgeModule.h头文件
接下来遵守RCTBridgeModule协议 如下:
@interface PushNative : NSObject
@end
=======================================
PushNative.m中
@implementation PushNative
RCT_EXPORT_MODULE(); // 导出桥接模块 默认模块名为当前class类名即PushNative,
也可自定义模块名 举个栗子:RCT_EXPORT_MODULE(RNNative);
RCT_EXPORT_METHOD(RNPushToNativeController:(NSString*)message){
dispatch_async(dispatch_get_main_queue(), ^{
###### 你要实现的原生代码 ######
});
}
解释代码:导出可供RN调用的方法 RNPushToNativeController是方法名、 (NSString*)参数类型、message参数。
以上就是iOS原生端的全部工作,是不是so esay !!!
RN调用:
导入原生模块集,它包含iOS端通过RCT_EXPORT_MODULE()导出的所有模块。
import {
NativeModules
} from 'react-native';
首先获取指定原生模块
let Push = NativeModules.PushNative;
前面的Push可随意命名,后面的PushNative必须和iOS导出的模块名一致。
调用iOS原生方法
Push.RNPushToNativeController('RN跳转Native');
iOS调用RN
在桥接文件里面进行sendAppEventWithName,RN里面addListener接收( 等同于iOS中的通知中心NSNotificationCenter )
componentDidMount(){
this.listener=NativeAppEventEmitter.addListener('getSelectDate',(data)=>{
进行对应的操作,在这里可以跳转页面
})
}
Android篇
官网上的原生模块理解
官网上有原生模块这一节,我的理解是这一节要教给我们,如何在RN中的JS代码中调用原生的JAVA代码,同样包括调用Toast和Dialog,这种我们已经写好的组件,但不包括View,View这种在另外一节中说道了。
首先需要知道的就是ReactContextBaseJavaModule
在java代码里面,继承了这个方法,就可以在里面写暴露给RN JS的方法,如下:
@ReactMethod
public void show(String message, int duration) {
Toast.makeText(getReactApplicationContext(), message, duration).show();
}
方法的上面一定会有 @ReactMethod标示,整个流程就不在这说,可以去中文网上看。
http://reactnative.cn/docs/0.38/native-modules-android.html#content
下面我说一下,在这里面关于activity相互调用的问题。
JS 调用原生activity
public MyNativeModule(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@ReactMethod
public void rnCallNative(String msg) {
Intent jumpIntent = new Intent(mContext, MainActivity.class);
mContext.startActivity(jumpIntent);
}
上面看着应该比较清晰,mContext就是本类中的context,然后执行java的startActivity方法,就能调用原生的activity,其中带参数啥的,会原生的应该都会。其实还是JAVA调JAVA,只是JS可以调用这个方法而已。
原生 调用JS Activity
这个时候,就需要理解RN这个东西,RN中的这句代码
AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);
我的理解就是一个activity,实际上,我们也是可以改造的,改造成framwork或layout等,这个需要有经验的去做。
理解了这一点就比较容易做到,在java代码中会有这么一个类。
public class MainActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "HelloWorldApp";
}
这里的HelloWorldApp,和上面注册的必须一样,这样的话,就理解了,如果你调用这个MainActivity,实际上就是进入到RN里面的index.android.js,这个里面了,然后可以根据带入的参数,选择到底绘制哪个画面。
jumpIntent = new Intent(context, MainActivity.class);
jumpIntent.putExtra("XXX", XXX);
context.startActivity(jumpIntent);
这样,你就携带参数,调用了这个activity。
然后呢,就可以使用一个回调方法,把我们携带的参数,从RN 的JS里面拿到
@ReactMethod
public void dataToJS(Callback successBack, Callback errorBack){
try{
Activity currentActivity = getCurrentActivity();
String XXXX = currentActivity.getIntent().getStringExtra("XXXX");
successBack.invoke(XXXX);
}catch (Exception e){
errorBack.invoke(e.getMessage());
}
}
这个是写在JS调用的方法里面的,这里getCurrentActivity,拿到的就是MainActivity的数据。
然后JS就可以调用了
componentDidMount(){
//进行从Activity中获取数据传输到JS
NativeModules.MyNativeModule.dataToJS((XXXX) => {
this.setState({
XXXXXX:XXXXXXX,
})
},
(result) => {
ToastAndroid.show('JS界面:错误信息为:'+result,ToastAndroid.SHORT);
})
}
在JS中的 componentDidMount方法中调用了JAVA代码以后,就可以拿到Activity的数据,然后,我们就可以判断要绘制哪个界面了。
整体思路就这样,很简单,还有其他的相互消息传递,监听,后续都会说到。