31

My project contains two fragment :

  • FragmentA : the fragment loaded by default when the app starts
  • FragmentB : replace the fragmentA when a click on a button is done.

This is the XML of my main view :

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

    <fragment
        android:id="@+id/main_fragment_container"
        android:name="fragmentA"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </fragment>

</LinearLayout>

When I wish to replace the FragmentA by the FragmentB, I use this code :

FragmentTransaction fragmentTransaction = getSupportFragmentManager()
            .beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB());
fragmentTransaction.commit();

This code works fine. My FragmentA is replaced by the new FragmentB. But when a click is done on the back button, I wish replace the FragmentB by the FragmentA by using popBackStackImmediate().

This is the code I use:

if (getSupportFragmentManager().getBackStackEntryCount() > 0){
    boolean done = getFragmentManager().popBackStackImmediate();
    fragmentTransaction.commit();
}

The function popBackStackImmediate return always false and the FragmentB still in foreground.

Why the FragmentA does not replace the FragmentB when I call popBackStackImmediate ? Is anybody has an idea to solve my problem?

thanks in advance

reevolt
  • 797
  • 1
  • 9
  • 24
  • Avoid using back stacks! it doesn't really help with the overall efficiency! use plain replace() or even better remove/add every time you want to navigate! Check my post on http://stackoverflow.com/questions/5802141/is-this-the-right-way-to-clean-up-fragment-back-stack-when-leaving-a-deeply-nest/26093368#26093368 – stack_ved Sep 29 '14 at 06:03

6 Answers6

48

You use the getSupportedFragmentManager() to replace FragmentA by FragmentB. But you call popBackStack() on the getFragmentManager().

If you are adding the Fragments to the android.support.v4.app.FragmentManager you also have to call popBackStack() on the same FragmentManager.

This code should solve the problem:

if (getSupportFragmentManager().getBackStackEntryCount() > 0){
    boolean done = getSupportFragmentManager().popBackStackImmediate();
}
Android Killer
  • 18,174
  • 13
  • 67
  • 90
owe
  • 4,890
  • 7
  • 36
  • 47
  • In my case I was using supportedFragmentManager in the activity and childFragmentManager in B to open C and when I had press backButton in C it was sending me to A instead of B – Beto Caldas Nov 04 '19 at 19:39
7

You should call

fragmentTransaction.addToBackStack(null);

after performing all operations such as add(), remove(), and replace() and Just before commit(). Only then this transaction will be added to backstack. Only then you will be able to return to previous fragment state with Back button. Details here.

SohailAziz
  • 8,034
  • 6
  • 41
  • 43
7

The problem is you're mixing Fragment and methods from the support library.

If you are using the support library, make sure:

  • your Activity extends from the android.support.v4.app.FragmentActivity
  • your Fragment extends from android.support.v4.app.Fragment
  • use getSupportFragmentManager() to get the android.support.v4.app.FragmentManager

Your code in the Activity would be:

if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
   getSupportFragmentManager().popBackStackImmediate();
}

Please be aware that if you would like to get the FragmentManager from the Fragment code, you have to use the getFragmentManager method, as explained in the documentation (probably that's the cause of some confusion if you don't have much experience).

If you are not using the support library:

  • your Activity extends from the android.app.Activity
  • your Fragment extends from android.app.Fragment
  • use getFragmentManager() to get the android.app.FragmentManager

Your code would be:

if (getFragmentManager().getBackStackEntryCount() > 0) {
   getFragmentManager().popBackStackImmediate();
}

fragmentTransaction.commit(); is not necessary in both cases, so remove it.

Also, please call fragmentTransaction.addToBackStack(null); just before the commit but after the other operations.

fasteque
  • 4,309
  • 8
  • 38
  • 50
1

I will suggest using the fragment replacement with Tag to produce the same result .

Add the fragment B to activity with tag

fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB(),"TAG_B");

Fragment A -> Fragment B [onBackPressed] -->Fragment A Override the onBackPressed() in the Activity files where ,

// check for fragment B and you are viewing fragment B

if (getSupportFragmentManager().findFragmentByTag("TAG_B")!=null)  
{
    fragmentTransaction.replace(R.id.main_fragment_container, new FragmentA(),"TAG_A");
}

addToBackStack("TAG") and popBackStackImmediate("TAG") always revert to fragment condition without any data in the UI right before fragment is created or added to activity !

Drunken Daddy
  • 7,326
  • 14
  • 70
  • 104
0

The problem is in the order of your code. Here are two things you need to pay attention to.

  1. You need to use addToBackStack() after your adding, replacing fragment. Then commmit()

  2. Then popBackStackImmediate can reverse the operation and it is working. I hope it solves the problem. I know it is an old post but I do encounter a similar problem and wish this update can help others. Below should be the correct order:

    FragmentTransaction fragmentTransaction =getSupportFragmentManager().beginTransaction();

    fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB());
    
    fragmentTransaction.addToBackStack(null);
    
    fragmentTransaction.commit();
    
Nensi Kasundra
  • 1,980
  • 6
  • 21
  • 34
Stan
  • 602
  • 6
  • 23
-1

If you are Struggling with addToBackStack() and popBackStack() then simply use

FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`

In your Activity In OnBackPressed() find out fargment by tag and then do your stuff

Fragment home = getSupportFragmentManager().findFragmentByTag("Home");

if (home instanceof HomeFragment && home.isVisible()) {
    // do you stuff
}

For more Information https://github.com/DattaHujare/NavigationDrawer I never use addToBackStack() for handling fragment.