55

I've been following the docs from Navigation Architecture Component to understand how this new navigation system works.

To go/back from one screen to another you need a component which implements NavHost interface.

The NavHost is an empty view whereupon destinations are swapped in and out as a user navigates through your app.

But, it seems that currently only Fragments implement NavHost

The Navigation Architecture Component’s default NavHost implementation is NavHostFragment.

So, my questions are:

  • Even if I have a very simple screen which can be implemented with an Activity, in order to work with this new navigation system, a Fragment needs to be hosted containing the actual view?

  • Will Activity implement NavHost interface in a near future?

--UPDATED--

Based on ianhanniballake's answer, I understand that every activity contains its own navigation graph. But if I want to go from one activity to another using the nav component (replacing "old" startActivity call), I can use activity destinations. What is activity destinations is not clear to me because the docs for migration don't go into any detail:

Separate Activities can then be linked by adding activity destinations to the navigation graph, replacing existing usages of startActivity() throughout the code base.

  • Is there any benefit on using ActivityNavigator instead of startActivity?
  • What is the proper way to go from activities when using the nav component?
Víctor Albertos
  • 8,093
  • 5
  • 43
  • 71
  • Google now recommand using one activity per app, so i'm not sure they will impement NavHost from Activity – Samuel Eminet May 21 '18 at 15:50
  • 1
    Yes I know but most apps out there are implemented using multiple activities. So it takes time to move from one implementation to another completely. So setting that bridge could help with the transition. – Víctor Albertos May 21 '18 at 15:52
  • Coming to this question in 2023. If we have multi module app, usage of Navigation component isn't that briliant with Activity transitions (can't move from it beucase there is tons of logic) + isn't a god Activities an anti-pattern? – Beemo Mar 22 '23 at 08:37

3 Answers3

66

The navigation graph only exists within a single activity. As per the Migrate to Navigation guide, <activity> destinations can be used to start an Activity from within the navigation graph, but once that second activity is started, it is totally separate from the original navigation graph (it could have its own graph or just be a simple activity).

You can add an Activity destination to your navigation graph via the visual editor (by hitting the + button and then selecting an activity in your project) or by manually adding the XML:

<activity
    android:id="@+id/secondActivity"
    android:name="com.example.SecondActivity" />

Then, you can navigate to that activity (i.e., start the activity) by using it just like any other destination:

Navigation.findNavController(view).navigate(R.id.secondActivity);
ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • Thanks for the answer. I've updated the initial question with two follow up questions. I would really appreciate if you answer them. – Víctor Albertos May 21 '18 at 17:36
  • 2
    You shouldn't be using ActivityNavigator itself, but just working with a `NavController`. – ianhanniballake May 21 '18 at 18:00
  • 2
    That was my first attempt and it didn't work: `{view} does not have a NavController set`. Be aware that that "view" reference contains only a `ConstraintLayout`. It seems that in order to work the view has to contain a Fragment, right? So if I don't want to instantiate a Fragment inside the Activity, the only way to navigate between graphs is using `ActivityNavigator `. Please correct me if I'm wrong. – Víctor Albertos May 21 '18 at 18:17
  • 3
    If you're not using any NavHost at all even in your first activity, then you're never going to actually get 90% of the benefit out of Navigation and should probably just continue to do what you are already doing. – ianhanniballake May 21 '18 at 18:25
  • As far as I know the only component that implements NavHost is a Fragment, so, I understand that if I'm using Activities without Fragments (in response to "to do what you are already doing") I should keep using startActivity. Thanks for the support. – Víctor Albertos May 21 '18 at 18:35
  • how to find navController from destination activity? – Sourav Bagchi Dec 06 '18 at 17:50
  • 1
    @SouravBagchi - a NavController only exists within a single Activity, so there's no access to a different Activity's NavController. – ianhanniballake Dec 06 '18 at 20:26
  • 4
    @ianhanniballake is there an "official" way to finish the current activity? e.g. MainActivity -> LoginActivity (has its own flow etc.) after doing the flow I want to close the activity (pop it) I've tried to use a "finish_flow" action with `app:popUpTo="NOT_SURE_WT_SHLD_GO_HERE" app:popUpToInclusive="true"` but with no success, also I really need this sep. activity as I don't want global nav ui elements during this flow. – Joaquim Ley Apr 07 '19 at 22:09
  • @ianhanniballake Please shed some light on how to finish() the source activity after navigating to a new activity destination from the navhost in source activity. Facing similar issues which Joaquim Ley mentioned. – Hari Kiran Jul 31 '20 at 21:55
  • @HariKiran - `requireActivity().finish()`, same as always. Navigation is never going to finish your activity for you. – ianhanniballake Jul 31 '20 at 22:04
  • so, how to send data back from the first Activity to the Fragment of the first Activity? @ianhanniballake – mantc_sdr Jun 09 '21 at 13:50
  • @mantc_sdr - the guide for [Getting a result from an activity](https://developer.android.com/training/basics/intents/result) explains how to return a result from the SecondActivity to a fragment in the FirstActivity. – ianhanniballake Jun 09 '21 at 19:20
13

I managed to navigate from one activity to another without hosting a Fragment by using ActivityNavigator.

ActivityNavigator(this)
                    .createDestination()
                    .setIntent(Intent(this, SecondActivity::class.java))
                    .navigate(null, null)
Víctor Albertos
  • 8,093
  • 5
  • 43
  • 71
  • 4
    seems navigate is not available now, do u got any replacement ! – CoDe Feb 06 '19 at 01:05
  • 53
    how is it better than `startActivity(new Intent(this,SecondActivity.class));` ? – rahimli Jun 23 '19 at 19:39
  • This is great, In my case is assume that SecondActivity is a nav host and is it possible to navigate to the fragment inside the SecondActivity? – a-rohim Dec 12 '19 at 14:34
  • You can use `ActivityNavigator(this).navigate(destination)` after creating destination with `val destination = ActivityNavigator(this).createDestination().setIntent(Intent(this, SecondActivity::class.java))` – Fatih Jul 30 '20 at 09:18
5

I also managed to navigate from one activity to another without hosting a Fragment by using ActivityNavigator.

Kotlin:

val activityNavigator = ActivityNavigator( context!!)
                activityNavigator.navigate(
                    activityNavigator.createDestination().setIntent(
                        Intent(
                            context!!,
                            SecondActivity::class.java
                        )
                    ), null, null, null
                )

Java:

ActivityNavigator activityNavigator = new ActivityNavigator(this);
activityNavigator.navigate(activityNavigator.createDestination().setIntent(new Intent(this, SecondActivity.class)), null, null, null);

nav_graph.xml

<fragment android:id="@+id/fragment"
        android:name="com.codingwithmitch.navigationcomponentsexample.SampleFragment"
        android:label="fragment_sample"
        tools:layout="@layout/fragment_sample">

    <action
            android:id="@+id/action_confirmationFragment_to_secondActivity"
            app:destination="@id/secondActivity" />

</fragment>
<activity
        android:id="@+id/secondActivity"
        android:name="com.codingwithmitch.navigationcomponentsexample.SecondActivity"
        android:label="activity_second"
        tools:layout="@layout/activity_second" />

Kotlin:

lateinit var navController: NavController
navController = Navigation.findNavController(view)
navController!!.navigate(R.id.action_confirmationFragment_to_secondActivity)