Android - Keeping the first fragment in backstack and don't re-create instance while replacing

1k views Asked by At

I've developed a material NavigationDrawer which has some menus. Each menu is associated with individual fragments. I would like to keep my FragmentHome() always alive in backstack so that whenever I switch to different fragment and come back, the FragmentHome() should be there as before.

This is the xml where I'm creating the fragments,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <include layout="@layout/toolbar" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <fragment
            android:id="@+id/navigation_drawer"
            android:name="NavigationDrawerFragment"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start" />
    </android.support.v4.widget.DrawerLayout>

</LinearLayout>

This is how I'm creating and replacing the fragments,

@Override
    public void onNavigationDrawerItemSelected(int position) {
    Fragment fragment = null;
    String title = getString(R.string.app_name);

        switch (position) {
        case 0:
            fragment = new FragmentHome();
            title = getString(R.string.app_name);

            break;
        case 1:
            fragment = new FragmentCategories();
            title = getString(R.string.title_categories);

        case 2:
            fragment = new FragmentMyPlaylist();
            title = getString(R.string.title_playlist);

        if (fragment != null) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.replace(R.id.container, fragment);
            fragmentTransaction.commit();

            // set the toolbar title
            getSupportActionBar().setTitle(title);
        }
}

The major problem I'm facing is, each fragment is created from the scratch whenever I'm replacing them. This is annoying and all of the components of the HomeFramgent() is re-created once again when they have already been created once.

UPDATE:

I made another solution for this issue which is to create individual framents in xml and replace them via the main container,

For this first I've created individual fragments that are associate with the fragment classes,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <include layout="@layout/toolbar" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <fragment
            android:id="@+id/FragmentHome"
            android:name="FragmentHome"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <fragment
            android:id="@+id/FragmentCategories"
            android:name="FragmentCategories"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
         <fragment
            android:id="@+id/FragmentMyPlaylist"
            android:name="FragmentMyPlaylist"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <fragment
            android:id="@+id/navigation_drawer"
            android:name="NavigationDrawerFragment"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start" />
    </android.support.v4.widget.DrawerLayout>

</LinearLayout>

Then I'm declaring each fragment by id in the main activity,

FragmentManager fm = getSupportFragmentManager();
        fragments[HOME] = fm.findFragmentById(R.id.FragmentHome);
        fragments[CATEGORIES] = fm.findFragmentById(R.id.FragmentCategories);
        fragments[PLAYLIST] = fm.findFragmentById(R.id.FragmentMyPlaylist);
        FragmentTransaction transaction = fm.beginTransaction();

        for (int i = fragments.length - 1; i > 0; i--) {
            transaction.hide(fragments[i]);
        }
        transaction.commit();

Now whenver I want to replace a frament I'm doing this inside onNavigationDrawerItemSelected(),

fragmentManager.beginTransaction().replace(R.id.container, new
FragmentHome()).commit();

This solves the issue of re-creating each fragments and is created once after the application runs. Again this gives me a restriction of not refreshing the other fragments. All fragments are created at once and not re-creating on change, which I don't want.

I'm looking for an efficient way so that only the FragmentHome() will stay in backstace and all other fragments will get refreshed while replacing.

Any kind of help would be greatly appreciated...

1

There are 1 answers

0
Bob Snyder On

Use FragmentManager.saveFragmentInstanceState to capture the state of your HomeFragment before it is replaced. You will need to declare a variable in the activity that hosts your fragments to save the result. When the HomeFragment is reselected, use Fragment.setInitialSavedState to restore the saved state of HomeFragment before adding it to the FragmentManager.