Android开发

[React-native]RN调用原生的深坑-For Andr

2018-10-16  本文已影响5人  蜗牛学开车

前言:最近闲着没事来搞一波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");

什么?你报错了?是下面的这种错误吗?

RN调原生错误

如果你是上面的错误(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的源码就明白了。

如果我的文章解决了你的问题,就请给个爱心(喜欢一下)。再见!!!。

上一篇下一篇

猜你喜欢

热点阅读