这是正确的方式来清理碎片回堆叠时,留下一个深度嵌套?
我正在使用Android兼容性库来实现片段,并扩展了布局示例,以便片段包含一个可以closures另一个片段的button。
在左侧的select窗格中,我有5个可选项目 – ABCDE
。
每个在细节窗格中加载一个片段(通过FragmentTransaction:replace
) – abcde
现在我已经扩展了片段e
以包含一个button,在另一个片段e1
也加载了一个button。 我已经完成了片段e
的onClick方法,如下所示:
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction(); ft.replace(R.id.details_frag, newFrag); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); ft.addToBackStack(null); ft.commit();
如果我做出以下select:
E - e - e1 - D - E
然后片段e
在详细信息窗格中。 这很好,我想要的。 但是,如果我点击back
button,它什么都不做。 我必须点击两次,因为e1
仍然在堆栈中。 此外,点击后,我在onCreateView中得到一个空指针exception:
为了“解决”这个问题,我selectABCDE
时添加了以下内容:
FragmentManager fm = getActivity().getSupportFragmentManager(); for(int i = 0; i < fm.getBackStackEntryCount(); ++i) { fm.popBackStack(); }
只是想知道这是否是正确的解决scheme,或者我应该做一些不同的事情?
那么取决于预期的行为,有几种方法可以解决这个问题,但是这个环节应该会给你提供所有最好的解决scheme,而不是奇怪的是来自Dianne Hackborn
http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42
基本上你有以下select
- 使用名称作为您的初始回退堆栈状态,并使用
FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
。 - 使用
FragmentManager.getBackStackEntryCount()
/getBackStackEntryAt().getId()
检索返回堆栈上的第一个条目的ID,以及FragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE)
。 -
FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
应该popup整个后端堆栈…我认为这是错误的文档。 (其实我猜这只是不包括您通过POP_BACK_STACK_INCLUSIVE
的情况下)
另一个干净的解决scheme,如果你不想popup所有堆栈条目…
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit();
这将首先清理堆栈,然后加载一个新的碎片,所以在任何给定的位置,堆栈中只有一个碎片
感谢Joachim的回答,我最终使用代码清除了所有的栈入口。
// In your FragmentActivity use getSupprotFragmentManager() to get the FragmentManager. // Clear all back stack. int backStackCount = getSupportFragmentManager().getBackStackEntryCount(); for (int i = 0; i < backStackCount; i++) { // Get the back stack fragment id. int backStackId = getSupportFragmentManager().getBackStackEntryAt(i).getId(); fm.popBackStack(backStackId, FragmentManager.POP_BACK_STACK_INCLUSIVE); } /* end of for */
我已经研究了很多清理Backstack,最后看到Transaction BackStack及其pipe理 。 这是最适合我的解决scheme。
// CLEAR BACK STACK. private void clearBackStack() { final FragmentManager fragmentManager = getSupportFragmentManager(); while (fragmentManager.getBackStackEntryCount() != 0) { fragmentManager.popBackStackImmediate(); } }
上述方法循环遍历堆栈中的所有事务,并立即将其删除。
注意:上面的代码有时不工作,我面对ANR,因为这个代码,所以请不要尝试这个。
以下更新方法从后台删除该“名称”的所有细分。
FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
- name如果非null,则这是要查找的前一个返回状态的名称; 如果find,所有状态到该状态将被popup。 该
- POP_BACK_STACK_INCLUSIVE标志可用于控制是否popup指定状态本身。 如果为null,则只popup最上面的状态。
我使用的是类似于使用while循环的代码,但是我在每个循环中调用了入口计数…所以我认为它有点慢
FragmentManager manager = getFragmentManager(); while (manager.getBackStackEntryCount() > 0){ manager.popBackStackImmediate(); }
// pop back stack all the way final FragmentManager fm = getSherlockActivity().getSupportFragmentManager(); int entryCount = fm.getBackStackEntryCount(); while (entryCount-- > 0) { fm.popBackStack(); }