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?