[React-native]RN调用原生的深坑-For Andr
前言:最近闲着没事来搞一波RN学习,搞了一个Demo练习一把。在RN调用原生启动原生页面时入了深坑(虽然前面也遇到很多的坑,信我,这个是最深的)。
**下面来看下网上的实现方式吧(我看了至少20篇博客以及1个视频教程,基本都是这么做的):
第一步:声明自定义ReactContextBaseJavaModule
用AndroidStudio打开你已经init好的项目(注意:是Android项目,init好之后会有Android和ios两个项目。),然后声明一个类继承ReactContextBaseJavaModule
,示例代码如下:
public class ReactNativeModule extends ReactContextBaseJavaModule {
private ReactContext reactContext;
ReactNativeModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return getClass().getSimpleName();
}
/**
* 定义个给RN调用的接口,RN可以调用这个方法并传置。这里一定要加上@ReactMethod这个注解。
* @param componentName 用来接收RN传递过来的数据。这里有几个参数分别是什么类型都看你的需求。
*/
@ReactMethod
public void openNativeVC(String componentName) {
//调起原生页面
CommonActivity.startRNPage(reactContext, componentName);
}
}
ReactContextBaseJavaModule
有一个抽象方法必须重写,返回这个Module的名称,建议与类名保持一致,就如示例代码中那样返回getClass().getSimpleName()
。
第二步:声明自定义ReactPackage
声明一个类实现ReactPackage
接口,示例代码如下:
public class NavigatorPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(new ReactNativeModule(reactContext));
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
上面这个一步主要是实现createNativeModules
这个方法,将我们刚刚声明的ReactContextBaseJavaModule
的子类ReactNativeModule
给创建出来并存入List集合返回给调用者。
第三步(注意:坑就在这一步):修改Application
找到MainApplication
(RN默认就是这个类名)这个Application的子类,在这个类里面你会发下下面这样一段代码:
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()
);
}
};
在getPackages方法的返回值List中加入我们刚刚声明的ReactPackage
的子类NavigatorPackage
,改完之后代码如下:
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(),
//加入我们自己声明的ReactPackage的子类。
new NavigatorPackage()
);
}
};
最后一步:在RN中调用
首先导包:
import {NativeModules} from 'react-native';
然后在你需要调用的地方调用即可。
NativeModules.ReactNativeModule.openNativeVC("RNDemo");
什么?你报错了?是下面的这种错误吗?
如果你是上面的错误(undefined is not an object (evaluating '_reactNative.NativeModules.ReactNativeModule.openNativeVC')
)那么恭喜你来对地方了。
我说过了,坑就在第三步,把你Application中构建ReactNativeHost的代码换成下面的:
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected ReactInstanceManager createReactInstanceManager() {
if (reactInstanceManager == null) {
reactInstanceManager = ReactInstanceManager.builder()
.setApplication(MainApplication.this)
.setBundleAssetName("index.bundle")
.setJSMainModulePath("index")
.addPackages(ReactManager.getInstance().getReactInstanceManagerPackages())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
}
return reactInstanceManager;
}
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
//重写了createReactInstanceManager方法后这里的返回值就没有什么意义了!所以这里直接返回空集合。
return Collections.emptyList();
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
重写createReactInstanceManager
方法自己动手构建ReactInstanceManager,而ReactInstanceManager对象最好是全局唯一(单例)的,所有地方都使用你自己构建的这个唯一的ReactInstanceManager。至于为什么这样就好了?我这里就不多讲了,因为产品喊我过去过需求去了,此刻我的内心很高兴(xiang kan ren)的。大家去看下ReactNativeHost的源码就明白了。