我将Android应用程序移植到蜂窝上,为了使用片段,我做了很大的重构。在以前的版本中,当我按下“主页”按钮时,我曾经做过一个操作ACTIVITY_CLEAR_TOP
,以重置后退堆栈。
现在我的应用只是一个带有多个片段的Activity,因此当我按下Home按钮时,我只是替换其中的一个片段。如何不用startActivity
与ACTIVITY_CLEAR_TOP
标志一起使用而清除我的后排堆栈?
我将Android应用程序移植到蜂窝上,为了使用片段,我做了很大的重构。在以前的版本中,当我按下“主页”按钮时,我曾经做过一个操作ACTIVITY_CLEAR_TOP
,以重置后退堆栈。
现在我的应用只是一个带有多个片段的Activity,因此当我按下Home按钮时,我只是替换其中的一个片段。如何不用startActivity
与ACTIVITY_CLEAR_TOP
标志一起使用而清除我的后排堆栈?
Answers:
从Joachim的答案中,从Dianne Hackborn:
http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42
我最终只是使用:
FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}
但同样可以使用以下方法:
((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
这会将所有状态弹出到指定状态。然后,您可以将片段替换为所需的片段
为@Warpzit的评论提供答案,并使其他人更容易找到它。
用:
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
充分尊重所有有关方面;我很惊讶地看到你们中有多少人可以通过简单的操作清除整个碎片
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
根据Android文档(关于name
论点-所主张的工作建议中的“空”)。
如果为null,则仅弹出最高状态
现在,我的确意识到我不了解您的特定实现(例如,在给定的时间点,您在后台堆栈中有多少个条目),但是当期望一个定义明确的答案时,我会全力以赴在更广泛的设备和供应商中的行为:
(供参考,与此同时)
FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStack();
}
接受的答案对我来说还不够。我不得不使用:
FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStackImmediate();
}
popBackStackImmediate()
是,同步执行事务通常是不明智的。
清除没有循环的堆栈
String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
其中name是addToBackStack()参数
getSupportFragmentManager().beginTransaction().
.replace(R.id.container, fragments.get(titleCode))
.addToBackStack(name)
我只想补充:-
使用以下命令从堆栈弹出
fragmentManager.popBackStack()
只是要从事务中删除碎片,而无法从屏幕上删除碎片。因此,理想情况下,它可能对您不可见,但是可能有两个或三个片段彼此堆叠,并且在按回车键时,UI可能看起来很杂乱,堆叠。
仅举一个简单的例子:
假设您有一个fragmentA,它使用fragmentmanager.replace()加载Fragmnet B ,然后执行addToBackStack来保存该事务。所以流程是:-
步骤1-> FragmentA-> FragmentB(我们移至FragmentB,但Fragment A在背景中,不可见)。
现在,您在fragmentB中进行了一些工作,然后按“保存”按钮,保存后应返回至fragmentA。
步骤2->在保存FragmentB的同时,我们返回FragmentA。
步骤3->因此,常见错误将是...在片段B中,我们将使用片段A执行片段Manager.replace()片段B。
但是实际上发生了什么,我们再次加载Fragment A,代替FragmentB。因此,现在有两个FragmentA(一个来自STEP-1,一个来自此STEP-3)。
FragmentsA的两个实例彼此堆叠,这可能不可见,但在那里。
因此,即使我们确实通过上述方法清除了后栈,事务也会被清除,但不会清除实际的碎片。因此,理想情况下,在这种情况下,只需按一下保存按钮,只需执行fm.popBackStack()或fm.popBackImmediate()即可返回fragmentA 。
因此,正确的Step3-> fm.popBackStack()返回到已经在内存中的fragmentA。
阅读文档并研究片段ID是什么,它似乎只是堆栈索引,因此可以使用:
fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);
零(0
)是堆栈的底部,因此弹出包含它的内容将清除堆栈。
CAVEAT:尽管上面的代码在我的程序中有效,但是我还是有些犹豫,因为FragmentManager文档从未真正指出id是堆栈索引。确实是这样,我的所有调试日志都没有,但是在某些特殊情况下不是吗?任何人都可以以一种或另一种方式确认这种情况吗?如果是这样,那么以上是最佳解决方案。如果没有,这是替代方案:
while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
fragmentManager..getBackStackEntryAt(0).getId()
而不是0?即使backstack条目ID在某些时候与堆栈索引不同,这也应该起作用。
只需使用此方法并传递Context&Fragment标签即可,我们需要删除该标签。
用法
clearFragmentByTag(context, FragmentName.class.getName());
public static void clearFragmentByTag(Context context, String tag) {
try {
FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();
for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
String backEntry = fm.getBackStackEntryAt(i).getName();
if (backEntry.equals(tag)) {
break;
} else {
fm.popBackStack();
}
}
} catch (Exception e) {
System.out.print("!====Popbackstack error : " + e);
e.printStackTrace();
}
}
嗨〜我找到了一个更好的解决方案,来自:https : //gist.github.com/ikew0ng/8297033
/**
* Remove all entries from the backStack of this fragmentManager.
*
* @param fragmentManager the fragmentManager to clear.
*/
private void clearBackStack(FragmentManager fragmentManager) {
if (fragmentManager.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
我这样工作:
public void showHome() {
getHandler().post(new Runnable() {
@Override
public void run() {
final FragmentManager fm = getSupportFragmentManager();
while (fm.getBackStackEntryCount() > 0) {
fm.popBackStackImmediate();
}
}
});
}
private boolean removeFragFromBackStack() {
try {
FragmentManager manager = getSupportFragmentManager();
List<Fragment> fragsList = manager.getFragments();
if (fragsList.size() == 0) {
return true;
}
manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}