ViewPager2 中的片段在返回父片段时被重新创建

Posted

技术标签:

【中文标题】ViewPager2 中的片段在返回父片段时被重新创建【英文标题】:fragments inside ViewPager2 are recreated when coming back to parent fragment 【发布时间】:2021-05-12 04:56:09 【问题描述】:

我的一个片段中有一个ViewPager2(我们称之为片段A)。 viewpager 使用FragmentStateAdapter 创建许多片段作为子片段(我们称这些片段为children)。当用户点击片段 A 中的按钮时,我将其替换为片段 B。

现在当用户点击设备返回按钮回到片段A时,我可以看到系统自动恢复了孩子(他们没有显示在viewpager中,但是他们的onCreateView方法被调用并保存了bundle交付给他们)。如何避免这种行为。我不希望孩子被自动重新创建和恢复。

【问题讨论】:

您有一个容器 (A),其中包含一个带有 N 个子项的 ViewPager。然后,您将这个容器 (A) 替换为 另一个容器 (B)。这意味着 ViewPager 中的所有片段(子项)都消失了,因为它们的父项 (A) 现在已经消失了。您究竟期望(或希望)在这里发生什么?您不可能想要将所有 viewPager 子项保留在内存中,这将是一种潜在的浪费(更不用说您甚至可能没有那么多内存)。那么这里有什么问题呢? @MartinMarconcini 问题是当我从后台弹出片段 A (通过单击后退按钮)时,viewpager 的片段会自动重新创建(它们的 onCreateView 方法被调用)。这就是我不明白为什么会发生以及如何避免。 嗯,ViewPager 是一个 View(事实上,ViewPager2 基本上是一个 RecyclerView)。当一个片段被弹出/隐藏/移除时,它的视图被销毁以释放资源,这自然包括所述视图的子视图。这就是片段的工作原理。如果您想保留它们的状态,请执行此操作,然后在重新创建视图时恢复状态。试图阻止 Fragment 破坏它的视图不是一个好主意。 @MartinMarconcini 我认为你误解了这个问题。当我替换片段 A 时,我确实希望它的所有子元素(包括查看器)都被销毁。但是当我回到片段 A 时,我可以看到,即使在将任何项目保存在 viewpager 中之前,也会调用 viewpager 中片段的 onCreate 方法。为什么?!谁在实例化这些片段,而我还没有向 viewpager 添加任何数据?! 确实我误会了;那么您可以分享创建 ViewPager 的代码吗?如果创建了 viewPager,它将与一个 Adapter 相关联,并会触发其 offscreenPageLimit 创建,但我敢肯定,其中不光是眼前一亮。我确定 VP 或 FragmentManager 正在“抢先聪明”并准备恢复以前的状态。 【参考方案1】:

简而言之,ViewPager 保存了一个内部项目列表(表示“页面”)。此列表中的项目数基于 mOffScreenPageLimit 值。默认情况下它设置为 1,但您可以通过调用 setOffscreenPageLimit(int limit) 来更改它。 例如:

viewpager.offscreenPageLimit = 3

【讨论】:

当我用另一个片段替换片段A时,我在onDestroyView方法中设置了viewPager=nullviewPagerAdapter=null,因此必须对viewpager进行垃圾回收。所以当我回到片段 A 时,为什么 viewpgaer 中的片段 onCreateView 被调用之前我将任何项目添加到 viewpager?!【参考方案2】:

在你的 onCreateView 方法中试试这个:

if(view ==null)

       //your oncreate view code
 

【讨论】:

你的意思是把fragment的视图保存在一个变量中,然后再恢复它?显然保存视图会消耗大量内存,没有意义。

以上是关于ViewPager2 中的片段在返回父片段时被重新创建的主要内容,如果未能解决你的问题,请参考以下文章

带有片段和 Jetpack 导航的 Viewpager2:恢复片段而不是重新创建它们

ViewPager2 中未显示图像(片段重新打开时)

焦点在 EditText 上时 ViewPager2 片段内容消失

ViewPager2 无法动态添加删除片段

底部导航片段中的 Viewpager2

如何更新 Tablayout 中的片段? (Viewpager2, FragmentStateAdapter)