so I'm using the android navigation component and I have a problem (2.2.0-rc04 version).
I have a welcomeFragment
(wF). From wF
I want to navigate to loginSellerFragment
(lSF) which is in a different navigation graph. I also don't want to remove wF
from backstack ( popUpTo, popUpToInclusive) when navigating to lSF
because a user might wanna go back to it.
<fragment
android:id="@+id/welcomeFragment">
<action
android:id="@+id/action_welcomeFragment_to_nav_onboarding_seller"
app:launchSingleTop="true"
app:destination="@id/nav_onboarding_seller" />
</fragment>
After navigating to lSF the backstack looks like this : wF lSF
We're on lSF
now, after login we want to go to feedFragment
(fF) which again is in a separate graph, but this time we want to clear all the backstack, because if a user is logged in and presses back he wants the app to exit, not to take him back to wF
or lSF
, so I used popUpTo="@id/loginSellerFragment popUpToInclusive='true"
in the action from lSF
to fF
.
<fragment
android:id="@+id/loginSellerFragment">
<action
android:id="@+id/action_login_to_seller"
app:destination="@+id/seller" . //this is the graph that has as firstDestination, feedFragment
app:launchSingleTop="true"
app:popUpTo="@id/loginSellerFragment"
app:popUpToInclusive="true" />
</fragment>
So in the backstack in this moment should be only fF because we removed everything up to lSF
(lSF
included)
The problem
When I'm on fF
and press back, the app doesn't close, instead it takes me to wF
( wF
should have been popped off the backstack already)
What I've tried
I've tried instead of popUpTo="@id/loginSellerFragment popUpToInclusive='true"
to use popUpTo="@id/welcomeFragment popUpToInclusive='true"
and it worked fine, but I'm pretty sure that this is not how it should be done. What am I missing here guys? Am I building the backstack wrong?
Also I've tried adding popUpTo="@id/welcomeFragment popUpToInclusive='true"
after navigating from wF
to lSF
, but this will break my user experience, because I don't want the app to exit when I'm still in the login process.
Please note that all of this fragments are in separate graphs.
To navigate I use FragmentDirections
e.g : findNavController.navigate(WelcomeFramgentDirections.actionXtoY())
app:popUpTo tells the Navigation library to pop some destinations off of the back stack as part of the call to navigate() . The attribute value is the ID of the most recent destination that should remain on the stack.
When navigating back to destination A, we also popUpTo A, which means that we remove B and C from the stack while navigating. With app:popUpToInclusive="true", we also pop that first A off of the stack, effectively clearing it.
launchSingleTop. var launchSingleTop: Boolean. Whether this navigation action should launch as single-top (i.e., there will be at most one copy of a given destination on the top of the back stack). This functions similarly to how android. content.
For me setting XML code didn't really solve the issue, had to use an extra line of code
findNavController()
.navigate(R.id.navigationFragment,
null,
NavOptions.Builder()
.setPopUpTo(R.id.splashFragment,
true).build()
)
It's not easy to grasp how Navigation Component manipulates backstack when you are using popUpTo
option.
The solution you mentioned in your question is correct:
You indeed should use popUpTo="@id/welcomeFragment" popUpToInclusive="true"
instead of popUpTo="@id/loginSellerFragment" popUpToInclusive="true"
.
I will try to explain why.
When you launch your application, your backstack will be empty and welcomeFragment
will be displayed.
When you navigate from welcomeFragment
to loginSellerFragment
, you will have welcomeFragment
in your backstack.
Than if you login, you will navigate from loginSellerFragment
to feedFragment
, and in backstack you will have loginSellerFragment
and welcomeFragment
.
Since you used popUpTo="@id/welcomeFragment"
, aplication will start to pop (remove) fragments from your backstack until it reaches welcomeFragment
. The welcomeFragment
will be also removed since we used popUpToInclusive="true"
.
Backstack should behave like FILO (First In Last Out) stack, so it will remove fragments in this manner:
First the top fragment will be removed and that is loginSellerFragment
.
Next, welcomeFragment
will be the top fragment. Since we need to pop up fragments until we reach welcomeFragment
this is where we stop, but welcomeFragment
will be also removed because of popUpToInclusive="true"
and your backstack will be empty.
If you try to navigate back from welcomeFragment
, you will exit app because your backstack is empty.
I hope that this helps. You could also read more about stack data structure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With