以编程方式移除ViewPager,何时(或如何确保)包含的Fragment被销毁?

5
事先搜索了这个问题,我可以找到许多关于动态添加和删除 ViewPager 中选定的 Fragment 的讨论。然而,我真正关心的是当使用 FragmentPagerAdapter 显示 Fragment 时,如何以编程方式从其包含的 ViewGroup 中“干净”地删除整个 ViewPager,并确保所包含的 Fragment 被正确销毁。
为了更详细地说明这个问题,我有一个横向两面板的布局,在左侧的 Fragment 中从列表中进行选择,然后将选择的内容放置在右侧的 FrameLayout 中。关键是内容可能会分页,因此必须以 ViewPager 格式显示内容,或者如果不分页,则直接用单个 Fragment 表示。
要显示单个 Fragment,我只需执行常规的 FragmentTransaction,将 Fragment 放入 FrameLayout 容器中。另一方面,如果要显示分页内容,则创建一个 ViewPager 并将其作为 FrameLayout 的子项添加进去。
当我需要更改内容时,如果之前的内容是独立的 Fragment,那么我可以通过 FragmentTransaction .remove() 简单地将其删除。当我这样做时,Fragment 会按预期经历 onPause() ... onDestroy() 循环。如果之前的内容是 ViewPager,那么我使用 .removeAllViews() 将其从 FrameLayout 中删除。在这里,我遇到了问题:我没有看到任何通过 FragmentPagerAdapter 在该 ViewPager 中保存的 Fragment 中调用任何 onPause() ... onDestroy() 方法。
从用户的角度来看,应用程序运行良好。经过多次删除 ViewPager 后,我可以看到 GC 回收内存。然而,我不喜欢这些 Fragment 的生命周期方法未被调用,因为我无法在其中进行任何清理,这似乎不“正确”。
有没有一种方法可以钩入,以便在 ViewPager 从其父级分离时删除 Fragment?换句话说,当我知道该 ViewGroup 不再使用时,我会在某个地方执行 FragmentTransaction(可能是在 FragmentPagerAdapter 中)来删除这些 Fragment
或者,我意识到我可以将 ViewPager 永久保留在右侧,并动态交换其中的 Fragment。当然,在某些时候它只包含一个页面并不重要。如果这是更好的方法,那么我将重构我的代码以执行此操作,但我希望听取您的意见。
1个回答

12
然而,我不喜欢这些Fragment的生命周期方法没有被调用,因为我无法在其中进行任何清理,并且这似乎并不“正确”。
如果那对你来说不太晚(例如堆问题),则它们应在活动被销毁时得到清理。
换句话说,在我知道ViewGroup不再使用时,我想要在某个地方执行FragmentTransactions(可能是在FragmentPagerAdapter中)来删除这些Fragments。
您没有执行将片段放在那里的事务。因此,您无法立即执行事务以删除片段。如果您切换到FragmentStatePagerAdapter,并调用setAdapter(null),那么根据我的源代码阅读,它应该导致页面中所有现有片段被销毁。 FragmentPagerAdapter从未使用remove(),但FragmentStatePagerAdapter通过其destroyItem()方法使用,当新适配器(或null)提供给setAdapter()时,所有现有片段都将通过destroyItem()销毁。()。

1
谢谢。我刚想到的一个解决方案是在destroyItem中使用FragmentManager来删除Fragment。我还从getItemPosition返回了PagerAdapter.POSITION_NONE并调用了notifyDataSetChanged()。通过在删除ViewPager之前执行此操作,FragmentonDestroy被调用,我很满意。你看到有什么问题吗?使用FragmentPagerAdapter的原因是我希望所有Fragment(数量较少)都保留下来,因为我的UI要求在单个接受按钮操作的响应中持久保存来自所有片段的用户数据。 - Trevor
1
@Trevor:“你看到这个有什么问题吗?” - 那应该没问题,但是在接受任何Android支持包更新时要小心。我们都知道,他们可能会改变行为,使得Android也尝试销毁片段,你可能会遇到错误并不得不撤销自己的销毁逻辑。 - CommonsWare
1
再次感谢,我理解了。看起来现在的情况是两全其美的:使用FragmentPagerAdapter意味着从Fragment分页时不会销毁它,但通过扩展destroyItem来删除片段,就像FragmentStatePagerAdapter一样,我可以在需要时删除Fragments。(我很欣赏要求所有附加的片段都保留下来,这样我就可以要求它们一次性保存用户输入数据,但否则我将不得不重构以使所有片段将此数据传递给主Activity,我宁愿避免这样做。) - Trevor
@Trevor,你能提供解决方案的代码吗?我会非常感激的,谢谢。 - N Jay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接