popBackStackImmediate在后台堆栈中未添加当前片段事务时不显示片段

时间:2017-07-24 10:42:38

标签: android android-fragments android-fragmentactivity fragment-backstack fragmentmanager

当序列中的所有片段都添加到backstack中时,Popbackstack工作正常,但是当其中一个事务没有添加到backstack中时,它不起作用。

这是我的导航:

1.更换片段以加载主片段。此事务未添加到backstack。

  1. 替换片段以加载登录片段。此事务已添加到backstack。

    3.更换片段以加载登录片段。此事务不会添加到backstack。

    现在,当我没有任何反应时按下按钮。理想情况下,它应该从登录片段转到主片段。 这是我在主要活动中的onbackpressed方法:

    @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 个答案:

答案 0 :(得分:1)

popBackstack只有'pop'在backstack中。 由于在按下时按LoggedInFragment替换LoginFragment时没有添加事务:

  • LoggedInFragment仍然存在,
  • 弹出LogInFragment
  • 显示HomeFragment

但是因为在HomeFragment之后添加了LoggedInFragment,HomeFragment会显示在它下面。因此,您无法将其视为LoggedInFragment隐藏。

一种解决方案是在LoggedInFragment替换LogInFragment时将事务添加到后台堆栈。 然后在onBackPressed中测试当前片段是否为LoggedInFragment。如果是这种情况,则将后向堆栈弹出到HomeFragment(不包括在内)。就像那样,LoggedInFragment和LogInFragment都会弹出。

修改

@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();
    }
}

为了按名称检索HomeFragment,您需要在HomeFragment替换当前片段时标记您的事务。通常我用片段的类简单名称标记所有事务,以便我可以重试任何片段:

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

答案 1 :(得分:0)

Eselfar对问题的解释是正确的,但他提供的代码对我来说不够通用。

我(希望)通过以下代码在一般情况下解决了这个问题:

@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();
}