Navigation Architecture Component singleTask or singleInstance in back stack - android

I have an BottomNavigationView and I would like to use it to navigate between three or four different fragments. If I instantiated one of the fragment I don't want do it again for same fragment I just want to reuse it.
NavOptions class providing launchSingleTop property to avoid to create new instance if that kind of instance already on top of the back stack. But how about singleTask or singleInstance option for back stack of fragments in navigation controller? If I no need to create new instance of fragment if it's already in the back stack and I just want to bring it on top? How to achieve this with Navigation Architecture Component of Jetpack?

I just stumbled across this problem and I finally found a solution. You can use popUpTo to achieve it.
So for example, you have fragment Home, Login, and Register.
From fragment Home, you navigate to Login, and then to Register, and to Login again. To prevent duplicate Login fragment, you should set popUpTo="#id/login_fragment" to the action.
<action
android:id="#+id/action_navigation_register_to_navigation_login"
app:destination="#id/navigation_login"
app:popUpTo="#id/navigation_login" />
Stack visualization:
Register
____
Login ==> Login ==> Login
____ ____ ____
Home Home Home

Related

MVVM Single Activity app return to a nested fragment with Navigation component after leaving app or launching intent

I am trying to return to a specific fragment after pressing the home button, sharing data with another app or switching activities.
Fragments in bottomNav:
A B C D
Fragments that are shared around the app and can be nested or navigated to from the bottomNav fragments:
E F G
Intended behaviour
User navigation stack:
A -> E
Presses home button and reopens app, stack remains the same.
A -> E
Actual Behaviour
User navigation stack:
A -> E
Presses home button and reopens app, brought back to first fragment
A
I tried to restore the navigation state by passing a bundle from navController.saveState() to a viewmodel during the Main Activity onPause method and restoring it with navController.restoreState() onResume to no avail. Is this not capable with the navigation component?
What you are looking for is called Multiple Backstack. Every Fragment in android maintains its own stack. So if you navigate to another Fragment in the ParentFragment, your ParentFragment will add the childFragment in its stack.
In your case, your ParentFragment is A and childFragment is E.
However, NavigationComponent has no vanilla support for Multiple Backstack. Ian Lake, the creator of NavigationComponent library is working on this issue since NavigationComponent was launched, and still haven't delivered on it. This doesn't mean he is not working on it, it simply means (as stated by Ian himself) that its harder to achieve because of Fragments API.
Coming back to your question, if you really want to implement MultipleBackstack then you can follow this project which pretty much anyone who wants MultipleBackstack with NavigationComponent first refers to. There is also a google sample that shows how to achieve this behavior.

Clear NavController backStack without knowing start destination's id

I'm trying to implement session expiry in my app. So when the user token has expired, I want to navigate to the Login Fragment and clear all existing destinations on the back stack. I know this is achievable with popUpTo and popUpToInclusive but a lot of conditional navigation is going on and the destination to popUpTo can't be determined at the point of navigating to the Login Fragment. Is there a way to simply navigate to a new fragment and clear every other destination on the back stack?
You can use app:launchSingleTop="true" in fragment action in navigation graph xml file.

Android navigate up the right graph when using NavController

I'm currently using Android Navigation Architecture in my project. It has a feature that can launch any fragment with a shortcut.
Suppose my navigation graph looks like this: A->B->C->D.
When I'm at fragment A , I directly navigate to fragment D with NavController.navigate(R.id.fragment_d). But when I'm press back button, it returns to fragment A. Is there any way to let the destination navigate back to its parent in navigation graph? (I mean, in this case, D back to C, B then back to A).
Thanks in advance.
Generally, you should always avoid creating a synthetic back stack when within your own app (and only do this when launching your app from a deep link outside your app, i.e., via an app shortcut).
However, you can approach this in one of two ways:
If you're okay with resetting the state on A, you can use NavDeepLinkBuilder to construct a set of Intents suitable for restarting your task on the chosen destination:
navController.createDeepLink()
.setDestination(R.id.destination_d)
.createTaskStackBuilder()
.startActivites()
Just call navigate() multiple times.
navController.navigate(R.id.destination_b)
navController.navigate(R.id.destination_c)
navController.navigate(R.id.destination_d)
I think you should be able to use navControler.navigateUp() on the destination if you have correctly introduced the parent fragment for your fragments. Also, consider the difference between the device back button and up back-arrow to go up to the parent

How can I navigate from an activity to another using Navigation Component and removing the first activity from the stack?

In my app I have two activities (AuthenticationActivity and MainActivity), each one with a nav graph and a big flow of fragments. I've created an action to navigate from a fragment of the AuthenticationActivity's graph to the MainActivity but it does not remove the AuthenticationActivity from the stack even if I set 'popTo' to the Authentication graph id.
finish authentication activity after navigate method:
button2.setOnClickListener {
view.findNavController().navigate(R.id.action_addItemFragment_to_mainActivity)
(activity as AuthenticationActivity).finish()
}

Navigation Component can't pop to exit app

Using Android's Navigation Component, I have 3 fragments hosted by a single Activity. The launch fragment is a splash screen fragment (A), if the user is not logged in, I launch the login fragment (B), if they are logged in, I launch a list fragment (C).
So launch routes are either A->B->C or A->C.
When you land on B or C, pressing back should kill the app. The NavigationController though is instead backs up to A (I think, A's onActivityCreated is certainly called at which point it crashes which is probably unrelated).
Pop behaviors in the graph editor for A -> B seem to allow me to pop to different fragments but there doesn't seem to be an option to just kill the app.
Do I really need to override onBackPressed for this behavior and just kill the activity? Because this is easier without the NavigationController, usually I would just finish an activity as I start a new one.
Open text tab in Graph Editor to view xml code, find your two actions A -> B and A -> C and put tag: app:clearTask="true", it's should kill you app when user press back button.
Example:
<fragment
android:id="#+id/launcher_fragment"
android:name="com.example.LauncherFragment"
android:label="launcher_fragment">
<action
android:id="#+id/action_launcher_to_login"
app:destination="#id/login_fragment"
app:clearTask="true"/>
<action
android:id="#+id/action_launcher_to_list"
app:destination="#id/list_fragment"
app:clearTask="true" />
</fragment>

Categories

Resources