1
votes

Popbackstack is working fine when all the fragments in the sequence are added in the backstack but isnt working when one of the transactions is not added in the backstack.

Here is my navigation:

1.Replace fragment to load home fragment. This transaction not added to backstack.

  1. Replace fragment to load login fragment. This transaction is added to backstack.

    3.Replace fragment to load loggedin fragment. This transaction is not added to backstack.

    Now, when i press back button once nothing happens. Whereas ideally it should go to the home fragment from logged in fragment. Here is my onbackpressed method in main activity:

    @Override
    public void onBackPressed() {
        if(getSupportFragmentManager().getBackStackEntryCount()>0)
        {
            FragmentManager.BackStackEntry backStackEntry = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1);
            String str = backStackEntry.getName();
            FragmentManager fm=getSupportFragmentManager();
            //getSupportFragmentManager().popBackStackImmediate();
            fm.popBackStack(str, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        }
        else {
            super.onBackPressed();
        }
    
    
    }
    
2
I think it works. Just you have both fragments displayed (your LoggedInFragment AND your HomeFragment). Since the LoggedInFragment has been displayed after the HomeFragment, the HomeFragment is not visible as hidden by the LoggedInFragment. You can't expect the LoggedInFragment to disappear when you press back as the transaction is not in the back stack.Eselfar
So to solve you issue, one solution could be to test if the current Fragment is the LoggedInFragment. If it's the case you remove the fragment from the container and then you pop the back stack to go back to home.Eselfar
wow u are absoloutely right Thanks a ton man.vipul bansal
but pls instead of comment, write it in answer so that we both can score a few points.vipul bansal
My solution above is a bit messy. Another one should be to add the transaction to the bs, then when the user press back you test if it's the LoggedInFragment and you pop the bs until the homeFragmentEselfar

2 Answers

1
votes

popBackstack only 'pop' what is in the backstack. Since you haven't add the transaction when replacing the LoginFragment by the LoggedInFragment when you press back:

  • the LoggedInFragment remains,
  • the LogInFragment is popped
  • the HomeFragment is displayed

But because the LoggedInFragment as been added after the HomeFragment, the HomeFragment is displayed underneath it. So you can't see it as hidden by the LoggedInFragment.

One solution is to add the transaction to the back stack when you replace the LogInFragment by the LoggedInFragment. Then in onBackPressed you test if the current fragment is the LoggedInFragment. If it's the case you pop the back stack up to HomeFragment (not inclusive). Like that both LoggedInFragment and LogInFragment will be pop.

EDIT

@Override
public void onBackPressed() {
    FragmentManager manager = getSupportFragmentManager();
    Fragment fragment = manager.findFragmentById(R.id.my_fragment_container);
    // If there is something in the back stack AND the current fragment is the LoggedInFragment
    if (manager.getBackStackEntryCount() > 0
            && fragment instanceof LoggedInFragment) {            
        manager.popBackStack(HomeFragment.class.getSimpleName(), 0);
    } else {
        super.onBackPressed();
    }
}

In order to retrieve the HomeFragment by name you need to tag your transaction when you replace the current fragment by the HomeFragment. Generally I tag all transactions with the fragment's class simple name so like that I can retried any fragment:

transaction.replace(R.id.my_fragment_container, fragment, fragment.getClass().getSimpleName());

0
votes

Eselfar's explanation of the problem is correct, but the code he provided wasn't generic enough for me.

I (hopefully) resolved this issue in a general case by the following code:

@Override
public void onBackPressed() {
    Fragment currentFragment = getCurrentFragment();

    if (mFragmentManager.getBackStackEntryCount() > 0) {

        // In a normal world, just popping back stack would be sufficient, but since android
        // is not normal, a call to popBackStack can leave the popped fragment on screen.
        // Therefore, we start with manual removal of the current fragment.
        removeCurrentFragment();

        mFragmentManager.popBackStack();
    } else {
        super.onBackPressed();
    }
}

private Fragment getCurrentFragment() {
    return mFragmentManager.findFragmentById(getContentFrameId());
}

private void removeCurrentFragment() {
    FragmentTransaction ft = mFragmentManager.beginTransaction();
    ft.remove(getCurrentFragment());
    ft.commit();

    // not sure it is needed; will keep it as a reminder to myself if there will be problems
    // mFragmentManager.executePendingTransactions();
}