facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.8k stars 24.29k forks source link

Android apps are always one activity, not following Android activity stack guidelines #2916

Closed tjerkw closed 8 years ago

tjerkw commented 9 years ago

If this is not supported, i dont see how can can create a big android app that behaves like a native app.

http://developer.android.com/guide/components/activities.html

mkonicek commented 9 years ago

React Native apps use custom handling for the Android Back button.

In JavaScript you can use the Navigator to transition between screens in your app.

Full example here: https://github.com/facebook/react-native/tree/master/Examples/Movies

mkonicek commented 9 years ago

The Facebook Ads Manager uses the same approach: https://play.google.com/store/apps/details?id=com.facebook.adsmanager&hl=en

petterliden commented 8 years ago

So what's the intention here? I wrote a native module to be able to launch new activities from the JS side, but it would be good to know if this is recommended/supported or if it can lead to unforeseen errors down the line (as RN continues to evolve). I haven't been able to find any documentation around having multiple RN activites hosting different root views / react instances in the same app, so a clarification (or pointer to docs) would be appreciated.

ide commented 8 years ago

I'm fairly certain that the main Facebook app will need to let one RN instance control several different root views (perhaps not Activities, depending on whether Facebook uses Activities). On iOS you can have one bridge control several root views FWIW.

ghost commented 8 years ago

Short explanation first: with "React-Fragment" and "React-Activity" I mean that they setup a new ReactRootView, ReactInstanceManager and call startReactApplication in onCreate/onCreateView and handle all the onPause/onResume callbacks etc..

So I have an existing app which has a NavigationDrawer and just switches out the Fragment below the Toolbar if a drawer item is selected. There I include a "React-Fragment" in the drawer which basically just shows a list of data. So far this works without any problems. But now I want open a new "React-Activity" if one of the list items is selected to show details about the selected item. I think the only way to do this currently is to build a Native Module which can launch the new "React-Activity" and this Activity then does all the React-Initialisation again. Also passing data here between Java/js every time isn't really straightforward.

As @petterliden already mentioned, it would be nice to know if this is something that is being worked on or if it's recommended to do it (having multiple Activities) at all.

mkonicek commented 8 years ago

You can share the bridge between several different fragments (and I think also Activities) in your app. You can even have several different ReactRootViews on the screen at the same time. It's an important use case for fb.

I don't know all the details but I think @AaaChiuuu might. It should probably be mentioned in these docs: https://facebook.github.io/react-native/docs/embedded-app-android.html

aaronechiu commented 8 years ago

Yup @mkonicek is right. You can have multiple Activities that use the same ReactInstanceManager. You'll want to make your own "ReactFragment" or "ReactActivity" and have a singleton "holder" that holds a ReactInstanceManager. When you need the ReactInstanceManager / hook up the ReactInstanceManager to the lifecycle of those Activities or Fragments, use the one provided by the singleton.

We do this internally at Facebook.

ide commented 8 years ago

@AaaChiuuu on that note -- would you know off the top of your head if you can have a ReactInstanceManager with a valid Context but zero root views?

aaronechiu commented 8 years ago

Yup, we definitely have that internally too.

ide commented 8 years ago

Haha cool. Thanks!

mkonicek commented 8 years ago

Awesome, thanks for the answer @AaaChiuuu! Added a section to the docs: https://github.com/facebook/react-native/commit/0bcd01e5c4c45068cdedbd3ede071283a77eb894

Everyone feel free to add more info there as needed. Will close this issue as the question has been answered.

lilac commented 8 years ago

@AaaChiuuu Could you explain how to have a instance manager set up without any root view? In my application architecture (https://github.com/lilac/statex), I create views using native languages, but handle events in the JS engine. Thus, I need to start a react native application without any root view.

My current android demo has some hack of react native to make it work, but I wish react native supports this kind of usage, where it is a pure JS execution environment.

aaronechiu commented 8 years ago

In the singleton holder init with:

ReactInstance mReactInstanceManager = ReactInstanceManager.builder()
  ...
  .setInitialLifecycleState(LifecycleState.BEFORE_RESUME)
  ...
  .build();
reactInstanceManager.getDevSupportManager().setDevSupportEnabled(false);
reactInstanceManager.createReactContextInBackground();

As a perf improvement, we call this before any view actually needs the ReactInstance so views don't need to wait for the instance to initialize when the instance is actually needed.

And calling a helper function in the Singleton from the Activity or Fragment's onDestroy():

public void maybeDestroy() {
  if (!retain) {
    mReactInstanceManager.onDestroy();
    mReactInstanceManager = null;
  }
}
jinzhaoyu commented 8 years ago

@AaaChiuuu Thanks ,I noticed "retain" in Singleton holder's "maybeDestroy()", But when set "retain" to false ? It should be always true ? And we have a lot of bundles , we call that bundle as "Plugin", those plugins is provide by difference developer , in this case ,how to share ReactInstanceManager ?

aaronechiu commented 8 years ago

Probably always true in your case. In some of our apps we don't use RN that often so keeping the instance around is less useful.

kaleai commented 8 years ago

+1