popBackStackImmediate 在当前片段事务未添加到后台堆栈时不显示片段
popBackStackImmediate not showing fragment when the current fragment transaction is not added in the backstack
当序列中的所有片段都添加到后台堆栈时,Popbackstack 工作正常,但当其中一个事务未添加到后台堆栈时,Popbackstack 无法正常工作。
这是我的导航:
1.Replace 加载主页片段的片段。此事务未添加到后台堆栈。
替换片段以加载登录片段。此事务已添加到后台堆栈。
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();
}
当序列中的所有片段都添加到后台堆栈时,Popbackstack 工作正常,但当其中一个事务未添加到后台堆栈时,Popbackstack 无法正常工作。
这是我的导航:
1.Replace 加载主页片段的片段。此事务未添加到后台堆栈。
替换片段以加载登录片段。此事务已添加到后台堆栈。
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();
}