Create only one instance of fragment while navigating to destinations(android)
Asked Answered
F

4

19

I am using Navigation component. when navigating I want to not create new instance of fragment if it already exists in backstack and pop that already existing in front.

    findNavController().navigate(RequestTransferFragmentDirections.actionRequestTransferFragmentToBlankFragment())

looking fowrard to find solution.

thanks.

Forcible answered 30/3, 2020 at 9:12 Comment(4)
Please add some more detail about what you're asking. Add some code to show what you've programmed or add a picture that could be useful. That way you are way more likely to get an answer to your question.Fractocumulus
I added the code. if it is not enough tell me what code should I add.Forcible
Hello did you find if there is a way to add one instance of the fragment?Zachar
Hello, yes i geuss I override fun onNavigationItemSelected(item: MenuItem): Boolean in Main activity and used navOptions. val navBuilder = NavOptions.Builder() val navOptions = navBuilder.setPopUpTo(item.itemId, true).build()Forcible
H
8

I faced the same problem, but the previous solutions didn't work for me unfortunately, in spite of they are supposed to fix the issue. Thanks btw! :)

This worked for me, adapted to your code would be:

findNavController().navigate(
    RequestTransferFragmentDirections.actionRequestTransferFragmentToBlankFragment()),
    NavOptions.Builder().setLaunchSingleTop(true).build()
)

I saw in the navigate() documentation that we can pass options, so by passing NavOptions.Builder().setLaunchSingleTop(true).build() will create a single instance of such fragment.

Holothurian answered 25/11, 2020 at 15:54 Comment(0)
W
6

I implemented the request of only one instance of a fragment type in this mode:

in navigation_graph.xml I declared a popUp-action to the fragment-destination

<action
    android:id="@+id/home_action"
    app:destination="@id/my_dest"
    app:popUpTo="@id/my_dest"
    app:popUpToInclusive="true" />

<fragment
    android:id="@+id/my_dest"
    android:name="com.project.android.fragments.MyFragment"
    android:label=""
    tools:layout="@layout/my_fragment_layout" />

In code I call the action

navController.navigate(R.id.home_action)
Worldshaking answered 29/3, 2021 at 11:24 Comment(1)
It worked for me. Thanks. This explanation helped me to understand better these action options: https://mcmap.net/q/261745/-navigation-popupto-and-popuptoinclusive-aren-39-t-clearing-the-backstackAmyl
I
5

Answering here because I had the same question. The following is a solution that worked for me. I ended up using the nav controller and popping to a backstack destination if it exists, if it doesn't exist then I navigate to it normally.

This looks like this:

if ( ! nav.popBackStack(R.id.action_profile, false)) {
    nav.navigate(R.id.action_profile)
}

nav.popBackStack(R.id.action_profile, false) will return false if the destination passed in is not in the backstack, otherwise it pops to it and returns true if it is. The boolean is used to pop the destination fragment as well.

From the docs:

/**
     * Attempts to pop the controller's back stack back to a specific destination.
     *
     * @param destinationId The topmost destination to retain
     * @param inclusive Whether the given destination should also be popped.
     *
     * @return true if the stack was popped at least once and the user has been navigated to
     * another destination, false otherwise
     */
    public boolean popBackStack(@IdRes int destinationId, boolean inclusive) {
        boolean popped = popBackStackInternal(destinationId, inclusive);
        // Only return true if the pop succeeded and we've dispatched
        // the change to a new destination
        return popped && dispatchOnDestinationChanged();
    }

Indonesia answered 31/7, 2020 at 6:22 Comment(0)
S
2

You can do something like:

bottomNavigation.setupWithNavController(navController)
bottomNavigation.setOnNavigationItemSelectedListener {
    if (it.itemId == R.id.navigation_home) {
        navController.popBackStack(R.id.navigation_home, false)
        true
    }
    else
        NavigationUI.onNavDestinationSelected(it , navController)
}

enter image description here

With the code above whenever the user clicks on the Home (R.id.navigation_home) item in the bottom navigation view, the app will navigate back to the existing instance of the Home destination using the popBackStack().

If the selects another destination in the bottom navigation, the app will navigates to that destination using NavigationUI.onNavDestinationSelected()

Stemware answered 4/11, 2020 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.