Fragment gets recreated on click from BottonNavigationBar with NavController

54 views Asked by At

So I have a GoogleMap in Fragment A, whenever I select fragment B from the BottomNavigationBar and select Fragment A again, the Map is reinitialised. However, if I go back to fragment A by back-press, the mapview is restored to it's previous state.

    private fun setupBottomNavigationBar() {
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.navigationContainer) as NavHostFragment
    navHostFragment.navController.setGraph(R.navigation.main_graph)
    NavigationUI.setupWithNavController(binding.bottomNavigationBar, navHostFragment.navController)

    binding.bottomNavigationBar.setOnItemReselectedListener {
        // Do nothing to ignore the reselection
    }
}

The fragment transaction are being handled by the NavigationComponenet itself.

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_graph"
app:startDestination="@id/home_graph">

<include app:graph="@navigation/home_graph"/>
<include app:graph="@navigation/captain_portal_graph"/>
<include app:graph="@navigation/accounts_graph"/>

</navigation>

My fragments extend this BaseFragment:

abstract class BaseFragment<TViewBinding : ViewDataBinding> : Fragment() {

private var innerBinding: TViewBinding? = null
protected val binding: TViewBinding get() = innerBinding ?: throw IllegalStateException("Trying to access the binding outside of the lifecycle.")

abstract val layoutId: Int

protected val baseActivity: BaseActivity<*>
    get() = activity as BaseActivity<*>

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    innerBinding = DataBindingUtil.inflate(inflater, layoutId, container, false)
    return binding.root
}

override fun onStart() {
    super.onStart()
    setupActionBar()
}

override fun onDestroyView() {
    super.onDestroyView()
    innerBinding = null
}

This official sample from Google is working as expected, I want to achieve the same behavior, what could I be doing wrong?

1

There are 1 answers

3
Purple6666 On

In your graph define your navigation action that leads to your map fragment with app:launchSingleTop="true".

app:launchSingleTop : 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)

source: https://developer.android.com/reference/androidx/navigation/NavOptions

to have the navigation component in sync with the normal back press navigation you must also add app:defaultNavHost="true" to your fragment container view.

the app:defaultNavHost="true" attribute ensures that your NavHostFragment intercepts the system Back button. Note that only one NavHost can be the default. If you have multiple hosts in the same layout (two-pane layouts, for example), be sure to specify only one default NavHost.

source: https://developer.android.com/guide/navigation/get-started