399

FragmentPagerAdapter和 和有什么不一样FragmentStatePagerAdapter

关于FragmentPagerAdapter谷歌的指南说:

此版本的分页器最适合在需要分页的情况下使用少数通常更静态的片段,例如一组选项卡。用户访问的每个页面的片段都将保存在内存中,尽管它的视图层次结构在不可见时可能会被破坏。这可能会导致使用大量内存,因为片段实例可以保持任意数量的状态。对于较大的页面集,请考虑FragmentStatePagerAdapter.

关于FragmentStatePagerAdapter

当有大量页面时,此版本的寻呼机更有用,更像列表视图。当页面对用户不可见时,它们的整个片段可能会被销毁,只保留该片段的已保存状态。FragmentPagerAdapter与在页面之间切换时潜在的更多开销相比,这允许寻呼机保留与每个访问页面相关联的内存少得多 。

所以我只有3个片段。但它们都是具有大量数据的独立模块。

Fragment1处理一些数据(用户输入)并通过活动将其传递给Fragment2,这只是一个简单的ListFragment. Fragment3也是一个ListFragment

所以我的问题是:我应该使用哪个适配器?FragmentPagerAdapter还是FragmentStatePagerAdapter

4

8 回答 8

313

就像文档说的那样,这样想。如果你要做一个像阅读器这样的应用程序,你不会希望一次将所有片段加载到内存中。您想Fragments在用户阅读时加载和销毁。在这种情况下,您将使用FragmentStatePagerAdapter. 如果您只显示 3 个不包含大量数据的“标签”(例如Bitmaps),那么FragmentPagerAdapter可能很适合您。另外,请记住,ViewPager默认情况下会将 3 个片段加载到内存中。Adapter您提到的第一个可能会破坏View层次结构并在需要时重新加载它,第二个Adapter仅保存状态Fragment并完全破坏它,如果用户随后返回该页面,则检索状态。

于 2013-09-11T17:57:12.570 回答
140

FragmentStatePagerAdapter:

  • 随着FragmentStatePagerAdapter,您不需要的片段被破坏。事务承诺从您的活动中完全删除片段FragmentManager

  • 状态FragmentStatePagerAdapter来自这样一个事实,即它将在销毁片段时保存您的片段BundlesavedInstanceState当用户导航返回时,将使用片段的状态恢复新片段。

片段页面适配器:

  • 相比之下FragmentPagerAdapter,没有任何作用。当不再需要片段时。FragmentPagerAdapter调用 detach(Fragment)事务而不是remove(Fragment).

  • 这破坏了片段的视图,但在FragmentManager.so 中创建的片段 FragmentPagerAdapter永远不会被破坏。

于 2014-07-29T09:42:24.290 回答
68

这是每个片段的日志生命周期,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调用。 onDestroyoffscreenPageLimitFragmentPagerAdapter

注意:我认为我们应该使用FragmentStatePagerAdapter一个ViewPager有很多页面的页面,因为它对性能有好处。

示例offscreenPageLimit:_

如果我们去 Fragment3,它将破坏Fragment1(或 Fragment5,如果有),因为offscreenPageLimit = 1. 如果我们设置offscreenPageLimit > 1不会破坏。如果在这个
例子中offscreenPageLimit=4我们设置了FragmentStatePagerAdapterFragmentPagerAdapteronDestroyViewonDestroy

Github 演示在这里

于 2017-11-28T02:30:04.837 回答
39

在文档或此页面上的答案中未明确说明的内容(即使@Naruto 暗示)是,FragmentPagerAdapter如果片段中的数据发生更改,则不会更新片段,因为它将片段保留在内存中。

因此,即使您要显示的 Fragment 数量有限,如果您希望能够刷新您的 Fragment(例如,您重新运行查询以更新 Fragment 中的 listView),您需要使用 FragmentStatePagerAdapter。

我在这里的全部观点是,片段的数量以及它们是否相似并不总是需要考虑的关键方面。您的片段是否是动态的也是关键。

于 2015-06-20T04:43:47.943 回答
14

FragmentPagerAdapter存储从适配器获取的先前数据,同时FragmentStatePagerAdapter在每次执行时从适配器获取新值。

于 2015-03-14T17:28:28.653 回答
4

FragmentStatePagerAdapter = 在 ViewPager 中容纳大量片段。由于此适配器在用户看不到片段时将其销毁,并且仅保留片段的 savedInstanceState 以供进一步使用。这种方式使用了少量内存,并且在动态片段的情况下提供了更好的性能。

于 2017-07-05T03:46:35.637 回答
3

FragmentPagerAdapter:用户访问的每个页面的片段将存储在内存中,尽管视图会被销毁。因此,当页面再次可见时,将重新创建视图,但不会重新创建片段实例。这可能会导致使用大量内存。当我们需要将整个片段存储在内存中时,应该使用 FragmentPagerAdapter。FragmentPagerAdapter 在事务上调用 detach(Fragment) 而不是 remove(Fragment)。

FragmentStatePagerAdapter:当 Fragment 实例对用户不可见时,它会被销毁,除了 Fragment 的已保存状态。这导致仅使用少量内存,并且可用于处理更大的数据集。当我们必须使用动态片段时应该使用,例如带有小部件的片段,因为它们的数据可以存储在savedInstanceState中。而且即使有大量片段也不会影响性能。

于 2020-01-21T09:59:24.343 回答
0

根据文档:

管理每个片段的生命周期的标准 PagerAdapter 有两种类型:FragmentPagerAdapter 和 FragmentStatePagerAdapter。它们都适用于片段,但它们更适合不同的场景:

  • 只要用户可以在片段之间导航,FragmentPagerAdapter 就会将片段存储在内存中。当片段不可见时,PagerAdapter 将分离它,但不会销毁它,因此片段实例在 FragmentManager 中保持活动状态。只有当 Activity 关闭时,它才会从内存中释放它。这可以使页面之间的过渡快速而流畅,但如果您需要很多片段,它可能会导致您的应用程序出现内存问题。

  • FragmentStatePagerAdapter 确保销毁用户看不到的所有片段,并仅将其保存的状态保留在 FragmentManager 中,因此得名。当用户导航回片段时,它将使用保存的状态恢复它。这个 PagerAdapter 需要的内存要少得多,但是在页面之间切换的过程可能会更慢。

于 2021-12-09T10:26:58.077 回答