【问题标题】:Correct way to remove all (Child) fragments删除所有(子)片段的正确方法
【发布时间】:2015-05-30 22:21:17
【问题描述】:

我在父片段线性布局(fragmentContainer)中动态加载了一堆子片段,然后当用户单击按钮时,我需要将它们全部删除并添加新片段。我不知道每次将添加的片段的确切数量。这是我一次删除所有碎片的方法

LinearLayout ll = (LinearLayout) view.findViewById(R.id.fragmentContainer);
ll.removeAllViews();

现在我可以使用片段事务方法添加新的了。 这种删除所有片段的方法非常简单,并且对我来说比使用 remove() 一个一个地删除每个片段更好,但这是一个好习惯吗?性能怎么样?你推荐更好的方法吗?

【问题讨论】:

  • 我相信您也应该使用片段事务删除片段。
  • @EpicPandaForce 我知道,但我必须通过一个循环,同时将它们一一删除,对吗?但是我的方式只用两行代码就可以立即清除所有内容。那么为什么要打扰呢?我的方法有什么缺点吗?
  • 你说你这样做然后添加新片段,为什么不使用 FragmentTransaction.replace 用新片段删除现有片段?
  • @harism 因为我不知道每次将添加的片段的确切数量。例如,首先可以添加 3 个片段,然后当用户单击按钮时,这次可能会添加 2 个片段。那么用什么代替什么?
  • 也许我误解了您的用例,但是根据文档替换,应该删除同一容器中的所有片段,然后使用作为参数给出的片段调用 add。这适用于首先添加的片段,对于后面的片段,您应该使用 FragmentTransaction.add。

标签: android android-fragments android-nested-fragment


【解决方案1】:

在 Kotlin 中你可以这样做:

repeat(fragmentManager.backStackEntryCount) {
    fragmentManager.popBackStack()
}

fragmentManager 可能是以下之一:

  • Activity.supportFragmentManager
  • Fragment.requireActivity().supportFragmentManager
  • Fragment.childFragmentManager
  • Fragment.parentFragmentManager 替换了 requireFragmentManager()

【讨论】:

    【解决方案2】:

    这是我一次删除所有碎片的方法

    不,不是。这是您从该容器中删除所有视图的方式。

    这种去除所有碎片的方法非常简单,对我来说很有效。

    它确实会删除任何碎片。它删除视图。这就是为什么该方法被命名为removeAllViews()

    但这是一个好习惯吗?

    没有。首先,当您旋转设备或进行配置更改时,您会注意到所有“移除”的片段都回来了。

    你有没有更好的方法推荐?

    跟踪未完成的片段(例如,使用ArrayList<Fragment>),然后遍历该列表,将每个片段传递给FragmentTransaction 上的remove() 方法。

    【讨论】:

    • 我在清单中使用 android:configChanges="orientation" ,因此删除的片段永远不会回来。但我最感兴趣的是你所说的 removeAllViews() 所以如果这个方法只是删除视图,所有以前加载的片段是否都保存在内存中?如果这是真的,那就不好了。所以实现我想要的唯一方法是遍历片段的arraylist并使用remove()一个一个地删除?
    • @ThanosF:“我在清单中使用 android:configChanges="orientation",所以删除的片段永远不会回来”——除此之外还有许多其他的配置更改,片段会回来所有这些配置更改。 “所有之前加载的片段是否都保存在内存中?” - 是的。 “所以实现我想要的唯一方法是遍历片段的arraylist并使用remove()一个一个地删除?” -- 是的。
    • 另外,请记住,片段系统的设计是围绕一个容器中一次只有一个片段(通常是FrameLayout 或其子类)而设计的。您可能会遇到尝试在一个容器中包含多个片段的其他副作用。
    • 无论我如何尝试,删除的片段都不会返回。实际上,这是关于在父片段中加载的子片段。他们试图模拟一种列表视图。 (每个片段代表一个列表Item)所以你觉得这不是一个好主意?
    • “实际上这是关于在父片段中加载的子片段”——啊。野马不能让我使用嵌套片段,所以我不熟悉这里关于配置更改的规则。 “所以你觉得这不是个好主意?” -- 我绝对不是粉丝。
    【解决方案3】:

    如果您只是想删除所有片段,请使用以下代码:

    FragmentManager fm = getActivity().getSupportFragmentManager();
    for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {    
        fm.popBackStack();
    }
    

    此代码只有在引用片段时使用FragmentTransactionadd 方法才有效。 popBackStack 方法用于移除。

    【讨论】:

    • 它有帮助。很简单。谢谢!
    【解决方案4】:

    我想建议你:使用 Kotlin 和 fragment-ktx 使用这个:

    在你的毕业典礼中:

    implementation "androidx.fragment:fragment-ktx:$androidXFragmentKtxVersion"
    

    在你的片段中

    childFragmentManager
          .findFragmentByTag(YOUR_TAG)?.let { fragment ->
            childFragmentManager.commit(allowStateLoss = true) {
              remove(fragment)
            }
          }
    

    如果您不使用 childFragmentManager,请改用 requireActivity().supportFragmentManager

    requireActivity().supportFragmentManage
              .findFragmentByTag(YOUR_TAG)?.let { fragment ->
                requireActivity().supportFragmentManage.commit(allowStateLoss = true) {
                  remove(fragment)
                }
          }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 2015-07-18
      • 2017-07-24
      • 1970-01-01
      相关资源
      最近更新 更多