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

popBackStackImmediate not showing fragment when the current fragment transaction is not added in the backstack

当序列中的所有片段都添加到后台堆栈时,Popbackstack 工作正常,但当其中一个事务未添加到后台堆栈时,Popbackstack 无法正常工作。

这是我的导航:

1.Replace 加载主页片段的片段。此事务未添加到后台堆栈。

  1. 替换片段以加载登录片段。此事务已添加到后台堆栈。

    3.Replace 加载登录片段的片段。此事务未添加到后台堆栈。

    现在,当我按下后退按钮时没有任何反应。而理想情况下,它应该从登录片段转到主片段。 这是我在 main activity:

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

popBackstack 只有 'pop' 后台堆栈中的内容。 由于您在按返回时将 LoginFragment 替换为 LoggedInFragment 时尚未添加事务:

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

但是因为LoggedInFragment是在HomeFragment之后添加的,所以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 替换当前片段时标记您的事务。通常我用片段的 class 简单名称标记所有交易,这样我就可以重试任何片段:

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

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