Fragments still added to backstack without calling addToBackStack, why?
android, android-fragments
Solution
So here what I found wrong with your code:
1) You are mixing together tags of `Fragment` and `BackStackEntry`.
String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();
So here you are getting the tag of `BackStackEntry` (not `Fragment`), which you adding or not in `fragmentTransaction.addToBackStack()`. Therefore, you are getting the wrong state and using it as current fragment.
2) It is generally not a good idea to store and reuse fragments like you do in your class fields: `FragmentA fragmentA;`. It can lead to problems with state and inflation, it is better to create them on every transaction, if you don't want to solve additional puzzles.
Problem
I making my fragment changer helper class and i have some issue with it. I call it `FragmentChanger` It has a `fragmentContainer`, which is a `ViewGroup`, that holds all the fragments i would like to show. I have made my own `replace(Fragment fragmentToChange, boolean needSaveToBackStack)` function which is: - Removing the old fragment fom the fragmentContainer - Adding a new fragment to the fragmentContainer - Optionally saves to backStack, wether `needSaveToBackStack` is `true` or `false`. The error is the follwowing: If i use my replace function with saving to backStack it is works properly, i can use my device's back button to stepping back and back to previsiously added fragments it is works like a charm. But when i would like to replace a fragment withOUT saving to backStack, there is something wrong in my code because when i stepping back, i can see on the screen the fragment that i NOT added to the backStack, and ALSO i can see an other previsiously added fragment at the same time! So i can see 2 fragments at the very same time, like this: This is my code: ``` //It is my helper class to handle replacing fragments. public class FragmentChanger { // fragmentTransaction FragmentTransaction fragmentTransaction; // the container for fragments ViewGroup fragmentContainer; // activity ofc Activity act; // Ctr: adding a default fragment to be the first so we can see it at app // start public FragmentChanger(Activity act, ViewGroup container, Fragment startingFragment) { this.act = act; this.fragmentContainer = container; fragmentTransaction = act.getFragmentManager().beginTransaction(); fragmentTransaction.add(container.getId(), startingFragment, startingFragment.getClass().getSimpleName()); fragmentTransaction.addToBackStack(startingFragment.getClass().getSimpleName()); fragmentTransaction.commit(); } // Replacing a fragment with an other one public void replace(Fragment fragmentToChange, boolean needSaveToBackStack) { fragmentTransaction = act.getFragmentManager().beginTransaction(); // replacing old fragment to the new one! fragmentTransaction.replace(fragmentContainer.getId(), fragmentToChange, fragmentToChange.getClass().getSimpleName()); // Some null checking, and if the new fragment is NOT equals the current // fragment if (getCurrentFragment() != null && getCurrentFragment() != fragmentToChange) { /*** Important** because something here is wrong ***/ // only addToBackStack when i want it, when needSaveToBackStack = // true! if (needSaveToBackStack) { fragmentTransaction.addToBackStack(fragmentToChange.getClass().getSimpleName()); } } // commiting changes fragmentTransaction.commit(); } // getting current Fragment private Fragment getCurrentFragment() { try { FragmentManager fragmentManager = act.getFragmentManager(); String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName(); Fragment currentFragment = act.getFragmentManager().findFragmentByTag(fragmentTag); return currentFragment; } catch (Exception ex) { ex.printStackTrace(); } return null; } // Logging the back stack public void logBackStack() { Log("Logging back stack:", "============="); FragmentManager fragmentManager = act.getFragmentManager(); int stackSize = fragmentManager.getBackStackEntryCount(); Log("Fragments count on the stack: ", stackSize + ""); for (int i = 0; i < stackSize; i++) { String fragmentTag = fragmentManager.getBackStackEntryAt(i).getName(); Log("Fragment on the stack: ", fragmentTag); } } private void Log(String str, String msg) { Log.i(str, msg); } } ``` And this is my MainActivity where i test my fragment helper class: ``` public class MainActivity extends Activity implements OnClickListener { // My 3 Fragment Classes, could be N other type, // in this example I only got 3 FragmentA fragmentA; FragmentB fragmentB; FragmentC fragmentC; // Button to add the fragments manually Button addA, addB, addC; // This is my activity's container, its a simple viewGroup // could be anything that can hold fragments ViewGroup fragmentContainer; // This is my fragment changer helper class that need some revision by you // guys FragmentChanger fragmentChanger; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //defining my adding buttons addA = (Button)findViewById(R.id.addAbtn); addB = (Button)findViewById(R.id.addBbtn); addC = (Button)findViewById(R.id.addCbtn); //setting onclicklistenrs addA.setOnClickListener(this); addB.setOnClickListener(this); addC.setOnClickListener(this); // defining my main container, this will holds fragments fragmentContainer = (ViewGroup) findViewById(R.id.fragmentContainer); // defining my fragments, each of them got an Activity (this), a // Container (mainContainer), and a Layout ofc. fragmentA = new FragmentA(this, fragmentContainer, R.layout.fragment_a_layout); fragmentB = new FragmentB(this, fragmentContainer, R.layout.fragment_b_layout); fragmentC = new FragmentC(this, fragmentContainer, R.layout.fragment_c_layout); // defining my fragment changer with an activity(this), a // container(mainContent) and a starting fragment to show! fragmentChanger = new FragmentChanger(this, fragmentContainer, fragmentA); } @Override public void onClick(View view) { if (view.equals(addA)) { //When adding fragmentA, i always want to save it to backstack fragmentChanger.replace(fragmentA, true); } else if (view.equals(addB)) { //I dont want to save to back stack when adding B //So if i press back button, i dont want to see fragmentB ever again. //(But i do see, this is the error.) fragmentChanger.replace(fragmentB, false); } else if (view.equals(addC)) { //When adding fragmentC, i always want to save it to backstack fragmentChanger.replace(fragmentC, true); } //After any modification on fragments, i log the backstack fragmentChanger.logBackStack(); } ``` } Ps: I can clearly see that fragmentB is never on the backStack if i logging the stack each time i replace a Fragment with my helper class. Then why is it appears if i push back button? I greatly appreciate any advice, this is my first attempt with using fragments with my own helper class and i would like to make it greatly usable.