交互的前提是你已经建立好了RN和Native,已经可以进行第一个Hello World。
React Native和Native之间的交互的前提是搭建一个Module和Package。Module可以理解为一个交流工具,它需要继承 ReactContextBaseJavaModule,我们写的一些交互方法全在这里面。Package它需要继承ReactPackage,主要是起个注册作用,将之前创建的Module添加到ReactNativeHost中,这样我们才能调用到。
建立Module
Module其中有两个方法实现,getName()是必须实现的,getConstants()自己看情况实现。
-
getName方法是需要返回你这个Module的一个名称,用来标识这个Module,常返回这个类的类名,省事又简单。
@Nonnull @Override public String getName() { return "MyRnModule"; }
-
getConstants方法是返回一个Map,官方的描述是:一个可选的方法,返回了需要导出给 JavaScript 使用的常量。它并不一定需要实现,但在定义一些可以被 JavaScript 同步访问到的预定义的值时非常有用。
@Nullable @Override public Map<String, Object> getConstants() { HashMap<String, Object> constants = new HashMap<>(); constants.put("keyName", "valueString"); ... return constants; }
建立Package
Package其中有两个方法需要实现,createNativeModules()和createViewManagers()。这里将mModule放在外面,不要写成return modules(new MyRnModule(reactContext)),我们在后面需要调用方法,需要这个对象。
-
createNativeModules方法是需要返回你需要注册的Module,上文的MyModule。
-
createViewManagers方法是返回一个UIManagerModule的视图管理列表(UIManagerModule具体作用自行学习),这里我们返回一个空列表。
public class MyRnPackage implements ReactPackage { public MyRnModule mModule; @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); mModule = new MyRnModule(reactContext); modules.add(mModule); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
注册
在MainApplication的getPackages()中注册新建的Package。
public class MainApplication extends Application implements ReactApplication {
private static final MyRnPackage myRnPackage = new MyRnPackage();
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(),
myRnPackage // ====> 这里就是我们添加的地方
//new MyRnPackage(); ===>不要写成这个样子,问你我们需要拿到这个reactPackage
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, false);
}
/**
* 获取 reactPackage
*/
public static MyRnPackage getReactPackage() {
return myRnPackage;
}
}
RN向Native发送数据
例如RN需要打开某一个Activity页面就可以在Module中写如下:
/**
* RN调用Native的方法
*/
@ReactMethod
public void StartActivity(String toActivity, String data) {
try {
// mReactContext:新建ReactApplicationContext mReactContext并在构造方法中赋值
Intent intent = new Intent(mReactContext, Class.forName(mReactContext.getPackageName()+"."+toActivity));
intent.putExtra("params", data);
// FLAG_ACTIVITY_NEW_TASK必须要有,要不然会报错
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mReactContext.startActivity(intent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
在跳转的页面onCreate()中可以接收传值:
Intent intent = getIntent();
if (intent != null) {
String params = intent.getStringExtra("params");
Log.e("信息:", "从react-native中传递过来的数据:" + params);
}
Native向RN发送数据
Native向RN发送数据,例如在Native获取设备的一些信息,转化为JSONString后发给React Native显示。
这里我们采用RCTDeviceEventEmitter方法来实现这一功能。RCTDeviceEventEmitter类似于Android原生中的广播,在MyModule中写如下代码:
/**
* Native调用RN
* RCTDeviceEventEmitter方法
* flag:一个标识,类似广播中的intentFilter.addAction("xxx")
* msg :传递的数据
*/
@ReactMethod
public void nativeCallRn(String msg) {
mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(flag, msg);
}
在js中接收数据,可以在componentDidMount()生命周期时进行数据获取
componentDidMount() {
// 这里的flag和上面的flag需要一致
DeviceEventEmitter.addListener(flag, (msg) => {
text = msg
})
}
在Activity中向RN发送数据:
/**
* 参数介绍:
* getReactPackage():MainApplication中获取MyRnPackage的方法
* mModule:拿到Package后再拿到具体的MyModule
* nativeCallRn():拿到Module后调用具体的方法
*/
MainApplication.getReactPackage().mModule.nativeCallRn("hello");