Prevent The Same Fragment From Stacking More Than Once ( addToBackStack)
Asked Answered
N

2

8

I have an Activity with three Fragments lets call them A, B and C. Fragment A is called in the Activity onCreate().

FragmentA fragA = new FragmentA();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.activity2_layout, fragA, "A");
transaction.commit();

And gets replaced with Fragment B or C when certain buttons are pressed, and the FragmentTransaction calls addToBackStack().

FragmentB fragB = new FragmentB(); //or C
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.activity2_layout, fragB, "B");  //or C
transaction.addToBackStack("B"); //or C
transaction.commit();

But lets say I call Fragment B three times in a row, how can I prevent it from stacking on to it self? And at the same time I want this to be possible: B called > C called > B called - BUT when i try to go back I want B to be opened only once ( C < B) instead of (B < C < B). So basically removing the first backStack with the new one.

Nan answered 17/11, 2015 at 13:54 Comment(0)
B
14

From How to resume Fragment from BackStack if exists, which maybe very similar to your query.

There is a way to pop the back stack based on either the transaction name or the id provided by commit (for eg. using the Fragment's class name as Thijs already mentioned):

String backStateName = fragment.getClass().getName();

Adding to backstack:

FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();

When popping:

getSupportFragmentManager().popBackStackImmediate (backStateName, 0); 

So before replacing fragment, we can check existance in backstack like:

boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);

if (!fragmentPopped){ //fragment not in back stack, create it.
    ...
    ...
    ft.addToBackStack(backStateName);
    ft.commit();
}

Please check the above question and the accepted answer for more explanation.

Burmese answered 18/11, 2015 at 5:27 Comment(1)
This is the better answer as it answers both questions :)Retractor
R
1

I have solved one of your questions, namely how can I prevent it from stacking on to it self?, in one of my own projects a while ago. This was the exact code I used there:

public void setContent(@NonNull Fragment fragment, boolean addToBackStack) {
    Fragment current = getSupportFragmentManager().findFragmentById(R.id.main_content);
    if (current == null || !current.getClass().equals(fragment.getClass())) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (addToBackStack) {
            transaction.addToBackStack(null).add(R.id.main_content, fragment).commit();
        } else {
            transaction.replace(R.id.main_content, fragment).commit();
        }
    }
}

What this code does is checks of what class the currently showing Fragment is and compare that to the fragment you want to replace it with. If they are the same, it doesn't do anything. This code can be shaped to fit your needs like so

Fragment newFragment = new FragmentB(); //OR FragmentC
Fragment current = getSupportFragmentManager().findFragmentById(R.id.activity2_layout);
if (!current.getClass().equals(newFragment.getClass())) {

    //POP BACKSTACK HERE LIKE EXPLAINED BELOW

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    final String tag = newFragment.getClass().getSimpleName();
    transaction.addToBackStack(tag);
    transaction.add(R.id.activity2_layout, newFragment, tag);
    transaction.commit();
} else {
    //THROW AN ERROR OR SOMETHING, HANDLE IT BEING THE SAME
}

Making sure that only one fragment of a certain type is present at a time could probably be achieved by popping the backstack until before the first occurence of the same fragment. I have not written any code for this but it shouldn't be too difficult to implement that feature. If you can't figure it out yourself, let me know and I will try to write you an example :)

Retractor answered 17/11, 2015 at 14:18 Comment(3)
Thank you :) No a example wont be necessary :) The only thing i need to figure out now is how to remove backStacks which have already been made, if it's even possible since I can't find any documentation or examples on that.Nan
I don't think that's possible at all. As far as I know, the FragmentManager has one and only one backstack. You can pop entries off and then add another to "replace" that amount of entries with the one new entry. As long as you do this before you commit(), you should be fine :)Retractor
@IvanJavorovic by remove backStacks do you mean clearing the back stack?Burmese

© 2022 - 2024 — McMap. All rights reserved.