0

In my Activity I setup the NavController in OnCreate:

navController = findNavController(this, R.id.NavHostFragment)

In my Fragments, I setup the NavController in onViewCreated:

navController = Navigation.findNavController(view)

The Activity only navigates to a few Fragments (e.g. SitesFragment, ContactsFragment, TasksFragment etc) from the NavigationView when item is clicked as below:

            R.id.nav_sites_fragment -> {
                navController.popBackStack(R.id.sitesFragment, true)
                navController.navigate(R.id.sitesFragment)
            }

In the Fragments, click events (in RecyclerViews mainly heading to other Fragments, such as SiteFragment, ContactFragment, TaskFragment etc) are handled as below:

            if (!navController.popBackStack(R.id.siteFragment, false)) {
                // not in BackStack
                navController.navigate(R.id.action_contactFragment_to_siteFragment)
                }

The problem is, Fragments from Fragment actions remain in the backstack even when I popBackStack in the Activity actions..

I think my understanding of backstack is not correct as I'm not sure what is going on - but that maybe I have created two separate instances of NavController?

EDIT: Although I have looked at this post How to clear navigation Stack after navigating to another fragment in Android, I am still finding same behaviour. PopBackStack in Activity is not clearing Fragments added to the backstack..

For example:

SITES -> SITE -> CONTACT -> CONTACTS should remove first three fragments, but backpress still returns to CONTACT..

Scamparelli
  • 671
  • 1
  • 9
  • 25

1 Answers1

0

Ok, so I found this post https://github.com/android/architecture-components-samples/issues/767.

I modified the code a bit and in my Activity I have the following function:

    private fun navigateWithClearStack(destination: Int) {
        val navController = findNavController(R.id.NavHostFragment)
        val navHostFragment: NavHostFragment = supportFragmentManager.findFragmentById(R.id.NavHostFragment) as NavHostFragment
        val inflater = navHostFragment.navController.navInflater
        val graph = inflater.inflate(R.navigation.business_navigation)
        graph.startDestination = destination

        navController.graph = graph
    }

Then, where I handle the NavigationView clicks:

    override fun onNavigationItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {

            R.id.nav_sites_fragment -> navigateWithClearStack(R.id.sitesFragment)
            R.id.nav_projects_fragment -> navigateWithClearStack(R.id.projectsFragment)
            R.id.nav_contacts_fragment -> navigateWithClearStack(R.id.contactsFragment)
            R.id.nav_tasks_fragment -> navigateWithClearStack(R.id.tasksFragment)
            
            R.id.nav_profile_fragment -> makeToast("Todo: Profile Fragment")
            R.id.nav_settings_fragment -> makeToast("Todo: Settings Fragment")

        }
        business_drawer_layout.closeDrawer(GravityCompat.START)
        return true
    }

So as users Navigate through app, Fragments are added to the BackStack (using popUpTo to deal with duplicates), but when user clicks shortcut back to one of 'starting' fragments, the graph is replaced, thus clearing the BackStack.. Which I think is kind of neat.

Scamparelli
  • 671
  • 1
  • 9
  • 25