0

I am trying to create a side navigation drawer based app using the latest navigation component library ('androidx.navigation:navigation-fragment-ktx:2.5.3' and 'androidx.navigation:navigation-ui-ktx:2.5.3') I tried to follow the basic template for creating a nav drawer, but everytime i click a menu item, it destroys the current fragment and creates a new one. also, when pressing back, we go back to start fragment, but the start fragment is also recreated, and is not in the state which it originally was. So my question is if it is possible to retain a fragment without causing a repeated destroy/create cycle ?

I know that the "state" of the fragment can be retained using activity viewmodel or save instance state, but at certain times, it would be more beneficial to just use a singleton fragment instead of recreating it. The following advance navigation sample from google does retain the navigation state, but my current doesn't seem to be even doing that, why?

code:

//navgraph sidenav advance.xml

<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"
    app:startDestination="@+id/nav_home">

    <navigation android:id="@+id/nav_home" app:startDestination="@+id/frag_home">
        <fragment
            android:id="@+id/frag_home"
            android:name="work.curioustools.fragmentpracticalsamples.side_navigation.HomeFragment"
            android:label="@string/menu_home"
            tools:layout="@layout/fragment_side_navigation" />
    </navigation>

    <navigation android:id="@+id/nav_gallery" app:startDestination="@+id/frag_gallary">
        <fragment
            android:id="@+id/frag_gallary"
            android:name="work.curioustools.fragmentpracticalsamples.side_navigation.GalleryFragment"
            android:label="@string/menu_gallery"
            tools:layout="@layout/fragment_side_navigation" />

    </navigation>

    <navigation android:id="@+id/nav_slideshow" app:startDestination="@+id/frag_slideshow">
        <fragment
            android:id="@+id/frag_slideshow"
            android:name="work.curioustools.fragmentpracticalsamples.side_navigation.SlideshowFragment"
            android:label="@string/menu_slideshow"
            tools:layout="@layout/fragment_side_navigation" />
    </navigation>
    
</navigation>
activity sidenav default.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"

    tools:ignore="ContentDescription"
    tools:openDrawer="start">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar">
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                tools:navigationIcon="@drawable/ic_sidenav"
                app:title="@string/app_name"
                app:popupTheme="@style/ThemeOverlay.MaterialComponents.Light" />

        </com.google.android.material.appbar.AppBarLayout>

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <androidx.fragment.app.FragmentContainerView
                android:id="@+id/fragment_navhost_default"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:defaultNavHost="true"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:navGraph="@navigation/navgraph_sidenav_advance" />
        </androidx.constraintlayout.widget.ConstraintLayout>

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            app:srcCompat="@android:drawable/ic_dialog_email"
             />


    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        tools:layout_width="100dp"
        app:menu="@menu/menu_side_navigation" />
</androidx.drawerlayout.widget.DrawerLayout>

// activity : SideNavigationDrawerDefaultActivity

class SideNavigationDrawerDefaultActivity : AppCompatActivity() {
    private  val binding by lazy {  ActivitySideNavigationDefaultBinding.inflate(layoutInflater) }
    private  val appBarConfiguration by lazy { AppBarConfiguration(setOf(R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow), binding.drawerLayout) }
    private  val navController by lazy {
        val navHost = supportFragmentManager.findFragmentById(R.id.fragment_navhost_default) as NavHostFragment
        navHost.navController
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        //setupActionBar
        setSupportActionBar(binding.toolbar)
        setupActionBarWithNavController(navController, appBarConfiguration)

        //setup side drawer
        binding.navView.setupWithNavController(navController)
        binding.fab.setOnClickListener { snack("hello",it) }
    }

    override fun onSupportNavigateUp() = navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()


}


ansh sachdeva
  • 1,220
  • 1
  • 15
  • 32

0 Answers0