在上一篇文章中,我们简单尝试了React Native向Android原生传递参数并调用Android方法。本文将介绍Android如何向React Native回传参数,即实现回调功能。
Android向React Native回传参数主要有以下几种方式:
- Callback
- Promises
- RCTDeviceEventEmitter(适用于多线程场景)
为了快速掌握核心用法,本文重点介绍第1种和第3种方式。第二种方式Promises的用法类似,可参考React Native官方文档。此外,本文还将演示如何从React Native启动原生Activity。
实现步骤
以下步骤延续自之前的项目,假设已创建React Native项目并配置了基础环境。
1. 创建原生模块类
首先,创建一个继承自ReactContextBaseJavaModule的类,例如TestModules。在该类中定义相关方法。
public class TestModules extends ReactContextBaseJavaModule {
private ReactApplicationContext mContext;
public TestModules(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Override
public String getName() {
// 此名称用于在React Native中调用
return "TestModules";
}
/**
* 从React Native调用原生模块,支持传递多种参数类型:
* Boolean -> Bool
* Integer -> Number
* Double -> Number
* Float -> Number
* String -> String
* Callback -> function
* ReadableMap -> Object
* ReadableArray -> Array
*/
@ReactMethod
public void Toasts(ReadableMap msg) {
ReadableNativeMap map = (ReadableNativeMap) msg;
HashMap map2 = map.toHashMap();
Toast.makeText(mContext, (String) map2.get("name"), Toast.LENGTH_SHORT).show();
}
/**
* Android向React Native回传参数(使用Callback)
*/
@ReactMethod
public void ToastFinished(String msg, Callback callback) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
WritableMap map = Arguments.createMap();
map.putInt("id", 1);
map.putString("name", "小明");
WritableArray array = Arguments.createArray();
array.pushString("哈哈1");
array.pushString("哈哈2");
map.putArray("sub", array);
callback.invoke(map);
}
/**
* Android向React Native发送事件(使用RCTDeviceEventEmitter)
*/
@ReactMethod
public void sendEvent() {
WritableMap map = Arguments.createMap();
map.putInt("id", 1);
map.putString("name", "路人甲");
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("sendEvent", map);
}
/**
* 启动原生Activity
*/
@ReactMethod
public void startActivity() {
Intent intent = new Intent(mContext, TestModuleActivity.class); // 确保在AndroidManifest.xml中注册Activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}
2. 实现ReactPackage
创建一个实现ReactPackage接口的类,用于注册原生模块。
public class TestPackages implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> nativeModules = new ArrayList<>();
nativeModules.add(new TestModules(reactContext));
return nativeModules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
3. 注册到MainApplication
在MainApplication类中添加自定义的ReactPackage。
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new TestPackages()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, false);
}
}
4. 在React Native中调用
在React Native组件中,导入NativeModules和DeviceEventEmitter,并调用定义的方法。
import React, { Component } from 'react';
import { View, Text, StyleSheet, NativeModules, DeviceEventEmitter } from 'react-native';
export default class App extends Component {
constructor() {
super();
this.state = {
name: 'To get started, edit App.js',
sendEvent: 'Send Event'
};
}
toast = () => {
let obj = {
id: 1,
name: "xiaohong"
};
NativeModules.TestModules.Toasts(obj);
};
toastFinishCallback = () => {
NativeModules.TestModules.ToastFinished("调用了原生并带有回调", (result) => {
this.setState({
name: result.name
});
});
};
sendEvent = () => {
NativeModules.TestModules.sendEvent();
};
componentWillMount() {
DeviceEventEmitter.addListener('sendEvent', (e) => {
this.setState({
sendEvent: e.name
});
});
};
startActivity = () => {
NativeModules.TestModules.startActivity();
};
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome} onPress={this.toast}>
Welcome to React Native!
</Text>
<Text style={styles.instructions} onPress={this.toastFinishCallback}>
{this.state.name}
</Text>
<Text style={styles.instructions} onPress={this.sendEvent}>
{this.state.sendEvent}
</Text>
<Text style={styles.instructions} onPress={this.startActivity}>
点击开启activity
</Text>
</View>
);
}
}
const styles = 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,
},
});
通过以上步骤,你可以实现Android原生模块向React Native回传参数,包括使用Callback和RCTDeviceEventEmitter方式,并能够启动原生Activity。这种方式增强了React Native与原生平台的交互能力,适用于复杂的移动应用开发场景。