Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment addToBackStack() and popBackStackImmediate() not working

I am currently building an application for Android (14 <= SDK <= 21) by using one ActionBarActivity and more Fragments, such as ListFragment and MapFragment, which are swapped within a single FrameLayout view.

The ActionBarActivity automatically replace/commit fragment A. Then, when the user tap a button, the hosting Activity replace/commit a new different fragment B. My goal is to let the user go back on fragment A as soon as she presses the back button.

Some code now.

MainActivity

public class MainActivity extends ActionBarActivity implements StopFragment.OnFragmentInteractionListener,
    StopItemFragment.OnFragmentInteractionListener {
...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentManager = getFragmentManager();
        fragmentManager.enableDebugLogging(true);
        ...
        if (fragmentManager.findFragmentById(R.id.content_frame) == null) {
            StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
            fragmentManager.beginTransaction()
                .replace(R.id.content_frame, list)
                .addToBackStack(null)
                .commit();
        }
        ...

        @Override
        public void onFragmentInteraction(String id) {
        selectItem(Integer.parseInt(id));
        }


       private void selectItem(int position) {
       StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
       ...
       fragmentManager.beginTransaction()
            .replace(R.id.content_frame, fragment)
            .commit();

       ...
       }
}


Problem

Even if addToBackStack() is called, when I am on fragment B, I am not able to go back to fragment A. MainActivity is directly closed. Yet I tried to manage the back stack by myself with no luck. I can see that the fragment is on the stack but if I call popBackStackImmediate(), fragment A is popped out and the fragment transaction is not performed. (first back press nothing happen, second activity closed)

I attach also the FragmentManager logcat:
http://pastebin.com/hFLHprL8

like image 549
Emanuele Avatar asked Nov 01 '14 22:11

Emanuele


3 Answers

For those, who are still looking for solution.

In the main Activity class (which is hosting the fragments)just override onBackPressed().

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

There is no onBackPressed() method in fragment, and this method is just for the activity. So,when we press the back key, the default behaviour of activity is shown, which is

you will either go to previous activity(if there is any) or the app will exit.

Now we need to override this method to tell the activity that when we press the back key, if there are any fragments in back stack, pop them out (and this is when the addToBackStack() comes into picture). Otherwise follow the default behaviour.

like image 62
Nicks Avatar answered Oct 18 '22 04:10

Nicks


Try this (Note add not replace for fragmentA, and addToBackStack() for fragmentB)

StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
        fragmentManager.beginTransaction()
            .add(R.id.content_frame, list)
            .commit();

and

StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
   ...
   fragmentManager.beginTransaction()
        .replace(R.id.content_frame, fragment)
        .addToBackStack("FragmentB")
        .commit();
like image 31
unchosen Avatar answered Oct 18 '22 02:10

unchosen


I had to call beginTransaction() and commit() of FragmentManager manually.
Solved by overriding onBackPressed():

@Override
public void onBackPressed() {
    ...
    if (fragmentManager.getBackStackEntryCount() > 1){
        fragmentManager.popBackStackImmediate();
        fragmentManager.beginTransaction().commit();
    } else {
        //handle finish
        finish(); // Closes app
    }
}
like image 5
Emanuele Avatar answered Oct 18 '22 03:10

Emanuele