1

I had the main navigation of my app set up nicely using SafeArgs. This was my nav_graph.xml:

<navigation
    android:id="@+id/nav_main"
    app:startDestination="@+id/fragment1">

    <fragment
        android:id="@+id/fragment1"
        android:name="org.example.Fragment1"
        android:label="Fragment 1">

        <action
            android:id="@+id/fragment1_to_fragment2"
            app:destination="@id/fragment2" />

    </fragment>

    <fragment
        android:id="@+id/fragment2"
        android:name="org.example.Fragment2"
        android:label="Fragment 2">
        
        <argument
            android:name="ARG_CATEGORY_ID"
            app:argType="long"/>

        <action
            android:id="@+id/fragment2_to_fragment3"
            app:destination="fragment3" />
            
    </fragment>

    <fragment
        android:id="@+id/fragment3"
        android:name="org.example.Fragment3"
        android:label="Fragment 3">
        
        <argument
            android:name="ARG_ITEM_ID"
            app:argType="long"/>
        
   </fragment>

</navigation>

And, using SafeArgs, I could happily navigate from Fragment2 to Fragment3 using:

NavDirections navDirections = Fragment2Directions.fragment2ToFragment3(myItemId);
navController.navigate(navDirections);

However, I then needed to add deep linking capability from notifications (having a backstack with arguments, as explained here), so I added a sub <navigation /> element to the end of nav_graph.xml - which became:

<navigation
    android:id="@+id/nav_main"
    app:startDestination="@+id/fragment1">

    <fra8gment
        android:id="@+id/fragment1"
        android:name="org.example.Fragment1"
        android:label="Fragment 1">

        <action
            android:id="@+id/fragment1_to_fragment2"
            app:destination="@id/fragment2" />

    </fragment>

    <fragment
        android:id="@+id/fragment2"
        android:name="org.example.Fragment2"
        android:label="Fragment 2">
        
        <argument
            android:name="ARG_CATEGORY_ID"
            app:argType="long"/>

        <action
            android:id="@+id/fragment2_to_fragment3"
            app:destination="fragment3" />
            
    </fragment>

    <fragment
        android:id="@+id/fragment3"
        android:name="org.example.Fragment3"
        android:label="Fragment 3">
        
        <argument
            android:name="ARG_ITEM_ID"
            app:argType="long"/>
        
    </fragment>
   
    <!-- This is the new sub navigation block that provides a backstack-with-arguments. -->
    <navigation
        android:id="@+id/nav_notification"
        app:startDestination="@id/fragment2Notif">

        <fragment
            android:id="@+id/fragment2Notif"
            android:name="org.example.Fragment2"
            android:label="Fragment 2">

            <action
                android:id="@+id/fragment2Notif_to_fragment3Notif"
                app:destination="@id/itemsGraph" />

        </fragment>

        <navigation
            android:id="@+id/itemsGraph"
            app:startDestination="@id/fragment3Notif">

            <argument
                android:name="ARG_ITEM_ID"
                app:argType="long"/>

            <fragment
                android:id="@+id/fragment3Notif"
                android:name="org.example.Fragment3"
                android:label="Fragment 3">

                <argument
                    android:name="ARG_ITEM_ID"
                    app:argType="long"/>

            </fragment>

        </navigation>
        
    </navigation>
   
</navigation>

Notice that the file now contains two occurrences of org.example.Fragment2.

This has brought me a new problem in that the second occurrence of org.example.Fragment2 (ie, fragment2Notif) has resulted in the original Fragment2Directions.fragment2ToFragment3(...) method being no longer available.

It's been replaced with Fragment2Directions.fragment2NotifToFragment3Notif(...) which works fine when in the notification part of my app but, when called from the main part of my app, as expected, results in:

IllegalArgumentException: navigation destination org.example:id/fragment2Notif_to_fragment3Notif is unknown to this NavController

It seems SafeArgs has overwritten the first Fragment2Directions object, meaning the only method it has is fragment2NotifToFragment3Notif(...).

So, how do I get the old fragment2ToFragment3(...) method back?

I expect I could solve the problem by subclassing Fragment2 to effectively duplicate it with a different name, Fragment2Notif, then using Fragment2 in my main nav and Fragment2Notif in the sub nav, but is there a more elegant/preferred way?

ban-geoengineering
  • 18,324
  • 27
  • 171
  • 253

1 Answers1

0

Looking through your nav_graph.xml file, I think the idea for nested graphs(series of destinations grouped within the parent navigation graph, in this case with id nav_main) is to add deep linking capability from notifications (having a backstack with arguments).

Other than this, with the assumption that the fragment2ToFragment3(...) is overwritten to fragment2NotifToFragment3Notif(...) by SafeArgs plugin, there is no significant change as one can still navigate to Fragment3 using fragment2NotifToFragment3Notif(...) since the two nested navigation graphs combined have same structural content as the parent navigation graph except for id attribute of the <fragment> tag.

So, in essence using fragment2NotifToFragment3Notif(...) instead of fragment2ToFragment3(...) won't hurt for this case.