这是正确的方式来清理碎片回堆叠时,留下一个深度嵌套?

我正在使用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在详细信息窗格中。 这很好,我想要的。 但是,如果我点击backbutton,它什么都不做。 我必须点击两次,因为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(); }