FragmentPagerAdapter
和 FragmentStatePagerAdapter
有什么区别?
关于 FragmentPagerAdapter
Google 的指南说:
这个版本的分页器最适合在需要分页的情况下使用少数通常更静态的片段,例如一组选项卡。用户访问的每个页面的片段都将保存在内存中,尽管它的视图层次结构在不可见时可能会被破坏。这可能会导致使用大量内存,因为片段实例可以保持任意数量的状态。对于较大的页面集,请考虑 FragmentStatePagerAdapter。
关于 FragmentStatePagerAdapter
:
当有大量页面时,此版本的寻呼机更有用,更像列表视图。当页面对用户不可见时,它们的整个片段可能会被销毁,只保留该片段的已保存状态。与 FragmentPagerAdapter 相比,这允许分页器保留与每个访问的页面相关联的内存少得多,但代价是在页面之间切换时可能会产生更多开销。
所以我只有3个片段。但它们都是具有大量数据的独立模块。
Fragment1
处理一些数据(用户输入)并通过 Activity 将其传递给 Fragment2
,这只是一个简单的 ListFragment
。 Fragment3
也是一个 ListFragment
。
所以我的问题是:我应该使用哪个适配器? FragmentPagerAdapter
还是 FragmentStatePagerAdapter
?
FragmentPagerAdapter
和 FragmentStatePagerAdapter
但什么是 FragmentStateAdapter
?
就像文档说的那样,这样想。如果你要做一个像阅读器这样的应用程序,你不会希望一次将所有片段加载到内存中。您希望在用户阅读时加载和销毁 Fragments
。在这种情况下,您将使用 FragmentStatePagerAdapter
。如果您只显示 3 个不包含大量数据的“标签”(如 Bitmaps
),那么 FragmentPagerAdapter
可能很适合您。另外,请记住 ViewPager
默认情况下会将 3 个片段加载到内存中。您提到的第一个 Adapter
可能会破坏 View
层次结构并在需要时重新加载它,第二个 Adapter
仅保存 Fragment
的状态并完全破坏它,如果用户随后返回该页面,则状态被检索。
FragmentStatePagerAdapter:
使用 FragmentStatePagerAdapter,您不需要的 Fragment 将被销毁。提交事务以从您的 Activity 的 FragmentManager 中完全删除该 Fragment。
FragmentStatePagerAdapter 中的状态来自这样一个事实,即当它被销毁时,它将从 savedInstanceState 中保存您的 Fragment 的 Bundle。当用户导航回来时,新的 Fragment 将使用该 Fragment 的状态恢复。
片段页面适配器:
通过比较,FragmentPagerAdapter 什么都不做。当不再需要该片段时。FragmentPagerAdapter 在事务上调用 detach(Fragment) 而不是 remove(Fragment)。
这破坏了片段的视图,但在 FragmentManager 中保留了片段的实例。因此在 FragmentPagerAdapter 中创建的片段永远不会被破坏。
这是 ViewPager
中每个片段的日志生命周期,其中有 4 个片段和 offscreenPageLimit = 1 (default value)
FragmentStatePagerAdapter
转到 Fragment1(启动活动)
Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
转到片段 2
Fragment3: onCreateView
Fragment3: onStart
转到片段 3
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart
转到片段4
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
FragmentPagerAdapter
转到 Fragment1(启动活动)
Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
转到片段 2
Fragment3: onCreateView
Fragment3: onStart
转到片段 3
Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart
转到片段4
Fragment2: onStop
Fragment2: onDestroyView
结论:当 Fragment 被克服时,FragmentStatePagerAdapter
调用 onDestroy
offscreenPageLimit
而 FragmentPagerAdapter
没有。
注意:我认为我们应该将 FragmentStatePagerAdapter
用于具有大量页面的 ViewPager
,因为它有利于性能。
offscreenPageLimit
的示例:
如果我们转到 Fragment3,它将销毁 Fragment1(或 Fragment5,如果有),因为 offscreenPageLimit = 1
。如果我们设置 offscreenPageLimit > 1
,它不会销毁。
如果在本例中,我们设置 offscreenPageLimit=4
,则使用 FragmentStatePagerAdapter
或 FragmentPagerAdapter
没有区别,因为 Fragment 从不调用 { 6} 和 onDestroy
当我们更改标签时
在文档或此页面上的答案中没有明确说明(即使@Naruto 暗示),如果片段中的数据发生更改,FragmentPagerAdapter
将不会更新片段,因为它将片段保留在内存中。
因此,即使您要显示的 Fragment 数量有限,如果您希望能够刷新您的 Fragment(例如,您重新运行查询以更新 Fragment 中的 listView),您需要使用 FragmentStatePagerAdapter。
我在这里的全部观点是,片段的数量以及它们是否相似并不总是需要考虑的关键方面。您的片段是否是动态的也是关键。
FragmentPagerAdapter
- 每个片段都包含一个列表。我的第一个列表称为“所有报告”,第二个列表是“最喜欢的报告”。在第一个列表中,如果我点击报告的星形图标,它会更新数据库以切换该报告的收藏状态。然后我扫过,我成功地在第二个列表的 UI 中看到了这个报告。所以也许这些实例被保存在内存中,但在某些情况下(例如,我的),内容实际上会为 FragmentPagerAdapter 更新
FragmentPagerAdapter
存储从适配器获取的先前数据,而 FragmentStatePagerAdapter
每次执行时都从适配器获取新值。
FragmentStatePagerAdapter = 在 ViewPager 中容纳大量片段。由于此适配器在用户看不到片段时将其销毁,并且仅保留片段的 savedInstanceState 以供进一步使用。这种方式使用了少量内存,并且在动态片段的情况下提供了更好的性能。
FragmentPagerAdapter:用户访问的每个页面的fragment都会存储在内存中,虽然视图会被销毁。因此,当页面再次可见时,将重新创建视图,但不会重新创建片段实例。这可能会导致使用大量内存。当我们需要将整个片段存储在内存中时,应该使用 FragmentPagerAdapter。 FragmentPagerAdapter 在事务上调用 detach(Fragment) 而不是 remove(Fragment)。
FragmentStatePagerAdapter:fragment实例在对User不可见时被销毁,除了fragment的保存状态。这导致仅使用少量内存,并且可用于处理更大的数据集。当我们必须使用动态片段时应该使用,例如带有小部件的片段,因为它们的数据可以存储在savedInstanceState中。而且即使有大量片段也不会影响性能。
根据文档:
管理每个片段的生命周期的标准 PagerAdapter 有两种类型:FragmentPagerAdapter 和 FragmentStatePagerAdapter。它们都适用于片段,但它们更适合不同的场景:
只要用户可以在片段之间导航,FragmentPagerAdapter 就会将片段存储在内存中。当片段不可见时,PagerAdapter 将分离它,但不会销毁它,因此片段实例在 FragmentManager 中保持活动状态。只有当 Activity 关闭时,它才会从内存中释放它。这可以使页面之间的过渡快速而流畅,但如果您需要很多片段,它可能会导致您的应用程序出现内存问题。
FragmentStatePagerAdapter 确保销毁用户看不到的所有片段,并仅将其保存的状态保留在 FragmentManager 中,因此得名。当用户导航回片段时,它将使用保存的状态恢复它。这个 PagerAdapter 需要的内存要少得多,但是在页面之间切换的过程可能会更慢。
不定期副业成功案例分享
FragmentPagerAdapter
使用它。FragmentPagerAdapter
的优点是片段之间的切换可以更快,因为实际的Fragment
对象不需要每次都重新构建。另一方面,这最终会使用更多的内存来保存内存中的片段对象。viewPager.setOffscreenPageLimit(2)
。