Skip to content Skip to sidebar Skip to footer

Fragment Backstack

Hi I have an activity and three fragments. When I replace my first fragment I am adding it to backstack. FragmentTransaction fragmentTransaction = getFragmentManager()

Solution 1:

Best way to achieve what you want is not to use fragment's backstack.

  1. Do not use addToBackStack() anywhere
  2. Keep your first fragment LoginFragment reference in the instance field mLoginFragment. Addition of your first fragment will look like this (probably in activity's onCreate():

    FragmentTransactionfragmentTransaction= getFragmentManager().beginTransaction();
      mLoginFragment = newLoginFragment();
      fragmentTransaction.replace(R.id.authentication_parent0_linear, mLoginFragment, LOGINTAG);
      fragmentTransaction.commit();
    
  3. in your activity override onBackPressed() method as following:

    @OverridepublicvoidonBackPressed() {
        Fragmentfr= getFragmentManager().findFragmentById(R.id.authentication_parent0_linear);
    
        // chek that mLoginFragment!=null, basically this should never happen! if (fr == mLoginFragment) {
            super.onBackPressed();
        } else {
            FragmentTransactionfragmentTransaction= getFragmentManager().beginTransaction();
          fragmentTransaction.replace(R.id.authentication_parent0_linear, mLoginFragment, LOGINTAG);
          fragmentTransaction.commit();
        }
    }
    

There is a cumbersome way to achieve the desired effect with the use of backstack. Here is how:

  1. do not call addToBAckStack() when creating fragment A
  2. When navigating from fragment A to B or to C, or to other fragments calladdToBackStack()
  3. When navigating deeper from B to C, etc. call popBackStack() before the transaction. Explanation of it can be found on SO. Like this:

    getFragmentManager().popBackStack();
    FragmentTransactionfragmentTransaction= getFragmentManager().beginTransaction();
      fragmentTransaction.replace(R.id.authentication_parent0_linear, newFragmentC(), "whatever");
      fragmentTransaction.addToBackStack(null);
      fragmentTransaction.commit();
    

Solution 2:

The Fragment manager allows you to put a Name (or TAG) on a given state. If you pass that same name to popBackStack it will pop states until it reaches that state. For example

// Add initial fragment
getFragmentManager()
    .beginTransaction();
    .replace(R.id.authentication_parent0_linear, newLoginFragment());
    .addToBackStack(TAG_FIRST_FRAGMENT_STATE) // The key is not passing null here
    .commit();

// Add other fragments like such
getFragmentManager()
    .beginTransaction();
    .replace(R.id.authentication_parent0_linear, newSignupFragment());
    .addToBackStack(null)
    .commit();


// On back press@OverridepublicvoidonBackPressed() {
    FragmentManagerfragmentManager= getFragmentManager();
    if (fragmentManager.getBackStackEntryCount() > 1) {
        fragmentManager.popBackStack(TAG_FIRST_FRAGMENT_STATE, 0);
    } else {
        super.onBackPress();
    }
}

Solution 3:

I fnally figured it out. based on Kirill K answer

publicclassMainActivityextendsActivityimplementsOnClickAuthentication,
    LoginInterface, SignupInterface {

FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;

@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    fragmentManager = getFragmentManager();
    Fragmentfragment= fragmentManager.findFragmentByTag("one");
    if (fragment == null) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction
                .replace(R.id.relative, newOneFragment(), "one");
        fragmentTransaction.commit();
    }
}

@OverridepublicvoidonClickAuthButton(int flag) {
    if (flag == 2) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction
                .replace(R.id.relative, newTwoFragment(), "two");
        fragmentTransaction.commit();
    } else {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.relative, newThreeFragment(),
                "three");
        fragmentTransaction.commit();

    }

}

@OverridepublicvoidswitchToSignup() {
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction
            .replace(R.id.relative, newThreeFragment(), "three");
    fragmentTransaction.commit();

}

@OverridepublicvoidswitchToLogin() {
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.relative, newTwoFragment(), "two");
    fragmentTransaction.commit();

}

@OverridepublicvoidonBackPressed() {
    FragmenttwoFragment= fragmentManager.findFragmentByTag("two");
    FragmentthreeFragment= fragmentManager.findFragmentByTag("three");
    if ((twoFragment != null && twoFragment.isVisible())
            || (threeFragment != null && threeFragment.isVisible())) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction
                .replace(R.id.relative, newOneFragment(), "one");
        fragmentTransaction.commit();
    } else {
        super.onBackPressed();
    }
}

}

Solution 4:

I have done it like this

1. Globally declare fragmentManager variable :

FragmentManagerfm= getFragmentManager();

2.onCreate method load your 1st fragment without using backstack

fm.beginTransaction().replace(R.id.content_frame , new main_fragment()).commit();

3. now when you will add new fragment then create a method which will check if the fragment is already in backstack or not and also it will handle clicking the same fragment events(if you are using frag in navigation drawer )

voidreplaceFragment(Fragment fragment) {
    Fragmentcurrent= fm.findFragmentById(R.id.content_frame);
    //Check if that frag is already openedif (!current.getClass().equals(fragment.getClass())) {


        StringbackStateName= fragment.getClass().getName();

        booleanfragmentPopped= fm.popBackStackImmediate(backStateName, 0);

        if (!fragmentPopped) {

            //fragment is not in back stack,so add it.FragmentTransactionft= fm.beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack(backStateName);
            ft.commit();

        }
    }
    else {
        //if fragmentPopped is true then it will auto pop up the fragment//so we dnt have to do anything here     
    }
}

4. now just pass your fragment class to

replaceFragment(new yourfragment());

5. now handle backpress

publicvoidonBackPressed() {

    int backStackEntryCount = fm.getBackStackEntryCount();


       if (backStackEntryCount == 0) {
            newAlertDialog.Builder(this)
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setTitle("Closing Activity")
                    .setMessage("Are you sure you want to close this Application?")
                    .setPositiveButton("Yes", newDialogInterface.OnClickListener() {
                        @OverridepublicvoidonClick(DialogInterface dialog, int which) {
                            finish();
                            System.exit(0);
                        }

                    })
                    .setNegativeButton("No", null)
                    .setOnCancelListener(newDialogInterface.OnCancelListener() {
                        @OverridepublicvoidonCancel(DialogInterface dialogInterface) {
                               //backpress over alert dialogfinish();
                                System.exit(0);
                        }
                    })
                    .show();

        } else {


            super.onBackPressed();
        }


    }

hope this will help you

Post a Comment for "Fragment Backstack"