1 RN调用Native方法
- 1、创建交互类Module,继承
ReactContextBaseJavaModule
; - 2、创建package,实现
ReactPackage
的方法,添加步骤1创建的交互类Module到package内; - 3、添加创建的自定义package到
ReactNativeHost
中的getPackages
方法中,向ReactNative注册原生模块;
1.1 导出Native端的showInfo提示方法
Native端导出
public class RNInterractModule extends ReactContextBaseJavaModule {
private ReactContext mReactContext;
public RNInterractModule(ReactApplicationContext reactContext) {
super(reactContext);
this.mReactContext = reactContext;
}
//导出的模块名字
@Override
public String getName() {
return "RNInterractModule";
}
//==============1、提示==============
@ReactMethod
public void showInfo(String info){
Toast.makeText(getReactApplicationContext(),info,Toast.LENGTH_SHORT).show();
}
}
复制代码
添加Module到自定义package:
public class RNInterractPackage implements ReactPackage{
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new RNInterractModule(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
复制代码
再添加package(此处展示完整的MainApplication方法,重写getPackages()
方法中添加)
public class MainApplication extends Application implements ReactApplication{
@Override
public ReactNativeHost getReactNativeHost() {
return reactNativeHost;
}
private ReactNativeHost reactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return true;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNInterractPackage()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
}
复制代码
1.2 RN端调用导出的showInfo方法:
我们在RN端把Native的方法通过一个共同的utils工具类引入,如下
import { NativeModules } from 'react-native';
//导出Native端的方法
export const { showInfo} = NativeModules.RNInterractModule;
复制代码
具体的RN页面使用时:
import { showInfo } from "../utils";
//通过Button点击事件触发
<Button
title='1、调用Native提示'
onPress={() => showInfo('我是原生端的提示!')}
/>
复制代码
调用效果:
1.3 RN回调Native
我们提供一个例子来模拟:目前的需求是做面包,RN端能提供面粉,但是不会做,Native端是有做面包的功能;所以我们需要先把面粉,传给Native端,Native加工好面包之后,再通过回调回传给RN端。
Native端提供方法
// 比如调用原生的方法处理图片、视频之类的,处理完成之后再把结果回传到RN页面里去
//TODO: 请务必注意 callback 并非在对应的原生函数返回后立即被执行——注意跨语言通讯是异步的,这个执行过程会通过消息循环来进行。
@ReactMethod
public void patCake(String flour, Callback successCallback,Callback errorCallback){
try{
//模拟异常,走reject
if (!flour.getClass().equals(String.class)){
throw new Exception("出错了,参数类型不匹配");
}
successCallback.invoke(patCakeUse(flour));
}catch (Exception e){
errorCallback.invoke(e.getMessage());
}
}
//使用RN端传递的参数字符串:"",调用Native端的做面包方法,加工成面包,再回传给RN
private String patCakeUse(String flour){
String cake = String.format("使用%s,做好了:\uD83C\uDF82\uD83C\uDF5E\uD83C\uDF5E\uD83C\uDF70\uD83C\uDF70\uD83C\uDF70",flour);
return cake;
}
复制代码
RN端调用:
//首先工具类里先引入
export const { showInfo,patCake } = NativeModules.RNInterractModule;
//具体页面使用
<Button
title='4、回调:使用面粉做蛋糕'
onPress={() => patCake('1斤面粉',
(cake) => alert(cake),
(error) => alert('出错了' + error.message))}
/>
复制代码
调用效果:
1.4 使用Promise回调
Native端提供方法
@ReactMethod
public void callNameTointroduction(String name, Promise promise){
try{
//模拟异常,走reject
if (!name.getClass().equals(String.class)){
throw new Exception("出错了,参数类型不匹配");
}
promise.resolve(introduction(name));
}catch (Exception e){
promise.reject(e);
}
}
private String introduction(String name){
return String.format("我的名字叫%s,今年18岁,喜欢运动、听歌...",name);
}
复制代码
RN端调用:
//首先工具类里先引入
export const { showInfo,patCake, callNameTointroduction} = NativeModules.RNInterractModule;
//具体页面使用
<Button
title='5、Promise:点名自我介绍'
onPress={
async () => {
try {
let introduction = await callNameTointroduction('小明');
showInfo(introduction);
} catch (e) {
alert(e.message);
}
}
}
/>
复制代码
调用效果:
2 Native发送通知到RN
实现自定义的发送RN消息类RNNotificationManager
public class RNNotificationManager {
//定义上下文
public static ReactContext mContext;
//发送事件到RN端
public static void sendRNEvent(String eventName, @Nullable WritableMap params){
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName,params);
}
}
复制代码
我们使用静态成员变量、方法,mContext
在自定义的RNInterractModule
为其赋值:
public class RNInterractModule extends ReactContextBaseJavaModule {
private ReactContext mReactContext;
public RNInterractModule(ReactApplicationContext reactContext) {
super(reactContext);
this.mReactContext = reactContext;
//赋值
RNNotificationManager.mContext = reactContext;
}
}
复制代码
然后就可以在需要给RN发送消息的地方调用:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
WritableMap params = Arguments.createMap();
params.putString("message","登录成功");
RNNotificationManager.sendRNEvent("kRNNotification_Login",params);
}
});
复制代码
RN端接收消息:
//添加监听
componentWillMount() {
this.subscription = DeviceEventEmitter.addListener('kRNNotification_Login',this.updateLoginInfoText)
}
//移除监听
componentWillUnmount() {
console.log('ActivityScene--------->', '移除通知');
this.subscription.remove();
}
复制代码
调用展示:
3 Native向RN自定义传参
- 在继承
ReactActivity
的RN入口Activity中,自定义CustomDelegate
(继承ReactActivityDelegate); - 然后重写
CustomDelegate
的getLaunchOptions()
方法,此处的Bundle即为要传递的参数Bundle; - 再重写RN入口Activity的
createReactActivityDelegate()
方法,返回CustomDelegate
实例; - RN端参数接收通过入口页面的
this.props
获取,具体可参考demo
示例:
public class ReactNativeActivity extends ReactActivity {
private String strData;
@Override
protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
if (intent != null){
strData = intent.getStringExtra("msgKey");
}
super.onCreate(savedInstanceState);
}
@Nullable
@Override
protected String getMainComponentName() {
return "RNTest";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new CustomDelegate(this,getMainComponentName());
}
//自定义ReactDelegate
class CustomDelegate extends ReactActivityDelegate {
private CustomDelegate(Activity activity, @Nullable String mainComponentName) {
super(activity, mainComponentName);
}
@Nullable
@Override
protected Bundle getLaunchOptions() {
Bundle bundle = new Bundle();
bundle.putString("msg",strData);
return bundle;
}
}
}
复制代码