与原生应用集成后,React-native应用在每次导航时都会重新启动

时间:2018-09-25 10:23:46

标签: javascript android react-native react-native-android react-native-navigation

我们正在尝试将新的React Native应用程序集成到现有的本机Android应用程序中。在RN官方docs之后,我们设法使其正常运行,但是在导航方面存在一些问题。

我们有本机和非本机(JS)屏幕,无论屏幕是本机还是非本机,我们都需要一种在所有屏幕之间导航的好方法。

我们尝试采用native-navigationreact-native-navigation来查看是否有解决我们的问题的方法,但实际上没有一个起作用。

当前,我们已经像这样注册了所有RN屏幕:

const provide = (store, Screen) => {
      return props => (
        <Provider store={store}>
          <Screen {...props} />
        </Provider>
      );
    };

    const store = configureStore();

    AppRegistry.registerComponent('Home', () => provide(store, HomeComponent));

我们还创建了一个称为“导航器”的本机模块,该模块具有名为openComponent的导航方法,该方法接受屏幕名称及其道具。 openComponent的实现如下:

// our native module code ...
     @ReactMethod
     public void openComponent(String name, String extra) {

         try {
             Intent intent = new Intent(this.getReactApplicationContext(), MyReactActivity.class);
             intent.putExtra("moduleName", name);
             intent.putExtra("extra", extra);

             getCurrentActivity().startActivityForResult(intent, 0);
         }
         catch (Exception e) {
             e.printStackTrace();
             Crashlytics.logException(e.getCause());
         }
     }

然后,每当我们要在RN端导航时,我们只需调用带有目标屏幕道具的自定义导航器即可。

当前方法的问题是,每当我们导航到基于RN的屏幕时,RN部分就会重新启动,这会导致Redux存储为空。

这是ReactActivity.java类的“ onCreate”方法的外观:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle initialProperties = new Bundle();
        initialProperties.putString("loginToken", HJSession.getSession().getSessionId());
        initialProperties.putString("username", HJSession.getSession().getUserName());
        initialProperties.putString("userId", HJSession.getSession().getUserId().toString());

        String moduleName = "topics";
        Bundle bundle = getIntent().getExtras();

        if (bundle != null) {
            moduleName = bundle.getString("moduleName");
            try {
                String extra = bundle.getString("extra");
                initialProperties.putString("extra", extra);
            }
            catch (Exception e) {
                e.printStackTrace();
                Crashlytics.logException(e.getCause());
            }
        }

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setJSMainModulePath("index")
                .addPackages(Arrays.<ReactPackage>asList(
                        new MainReactPackage(),
                        new RNFirebasePackage(),
                        new RNFirebaseMessagingPackage(),
                        new RNFirebaseNotificationsPackage(),
                        new RNI18nPackage(),
                        new VectorIconsPackage(),
                        new HJRNPackages(),
                        new NativeNavigationPackage()
                ))
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

        mReactRootView.startReactApplication(mReactInstanceManager, moduleName, initialProperties);

        setContentView(mReactRootView);
    }

2 个答案:

答案 0 :(得分:0)

ReactActivity.java中,可以检查Bundle savedInstanceState

...以控制何时实例化React应用程序:

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    /* it's always NULL on first run */
    if (savedInstanceState == null) {

        Bundle initialProperties = new Bundle();
        initialProperties.putString("loginToken", HJSession.getSession().getSessionId());
        initialProperties.putString("username", HJSession.getSession().getUserName());
        initialProperties.putString("userId", HJSession.getSession().getUserId().toString());

        String moduleName = "topics";
        Bundle bundle = getIntent().getExtras();

        if (bundle != null) {
            moduleName = bundle.getString("moduleName");
            try {
                String extra = bundle.getString("extra");
                initialProperties.putString("extra", extra);
            } catch (Exception e) {
                Crashlytics.logException(e.getMessage());
                Log.e("ReactActivity", e.getMessage());
            }
        }

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(getApplication())
            .setJSMainModulePath("index")
            .addPackages(Arrays.<ReactPackage>asList(
                new MainReactPackage(),
                new RNFirebasePackage(),
                new RNFirebaseMessagingPackage(),
                new RNFirebaseNotificationsPackage(),
                new RNI18nPackage(),
                new VectorIconsPackage(),
                new HJRNPackages(),
                new NativeNavigationPackage()
            ))
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build();

        mReactRootView.startReactApplication(mReactInstanceManager, moduleName, initialProperties);
        setContentView(mReactRootView);
    }
}

答案 1 :(得分:0)

实际上,对于您遇到的问题,您应该在Gitlab或Github上上传有此问题的项目的很小一部分,并将其链接放在此处,因此我们可以提供更好的帮助。

实际上,我是JavaScriptReactReact Native的开发人员,我无法帮助任何本地用户,但是绝对可以,我相信您和您的同事选择了错误的方式为您的应用程序。

React Native是一个不稳定的JavaScript项目,具有不稳定的本地代码,这些代码会随时间而变化,因此您应该仅使用JavaScript来编写所有功能。就像Sophie Albertthis article中所说的那样,他们想对React Native进行较大的更改,因此,最好使用JavaScript而不是本机( Java,目标C)。

起初,我认为您在react-native-navigation上的选择是错误的。为什么不使用react-navigation

由于基于react-navigation的{​​{1}}的99.7%以及Facebook团队更改的原生方面,因此不会影响您的项目,因此开发和调试非常容易。绝对可以,因为您的项目基于JavaScript,因此可以使用Redux之类的所有趋势库。

我和我的同事正在为Sheypoor开发一个大型JavaScript应用程序,除了初始屏幕上所有基于React Native的应用程序,在输入测试中我们都没有得到甚至是一次崩溃,错误或意外重启。

如果可能的话,将导航回滚到我们选择的完整JavaScript导航库,例如JavaScript。如果您上传了一个复制存储库,那么我可以比这种情况更好地帮助您。但我提出了一些代码结构来帮助您回滚到react-navigation

我们项目的react-navigation

index.js

我们应用的根文件import { AppRegistry } from 'react-native'; import App from './app/App'; import { name as appName } from './app.json'; AppRegistry.registerComponent(appName, () => App); 文件:

App.js

import React from 'react'; import { Provider } from 'react-redux'; import RootNavigation from './RootNavigation'; import { onNavigationStateChange } from './utils/routes'; import configureStore from './redux/configureStore'; const store = configureStore(); const App = () => ( <Provider store={store}> <RootNavigation onNavigationStateChange={onNavigationStateChange} /> </Provider> ); export default App; 文件,但不是现在用于我们先前的提交。由于复杂性,我不建议使用新版本:

RootNavigation.js

最后是import { createSwitchNavigator } from 'react-navigation'; import { Loading, Dashboard, SignInStack, ListingManagement } from './screens'; const RootNavigation = createSwitchNavigator( { Loading, SignInStack, Dashboard, ListingManagement }, { initialRouteName: 'SignInStack' } ); export default RootNavigation; 的早期版本:

package.json

使用这些代码和配置,我们什至没有给出一个错误。