FragmentPagerAdapter和FragmentStatePagerAdapter的区别是什么?

FragmentPagerAdapterFragmentStatePagerAdapter之间的区别是什么?

关于FragmentPagerAdapter谷歌的指南说:

此版本的寻呼机最适合在有少量的 通常需要分页更多的静态片段,例如一组 选项卡。用户访问的每个页面的片段将被保留 内存,尽管它的视图层次结构可能在不可见时被破坏。 这可能导致使用大量的内存,因为片段 实例可以保留任意数量的状态。对于较大的电视机

关于FragmentStatePagerAdapter:

此版本的寻呼机在有大量数据时更有用 页面,工作起来更像一个列表视图。当页面不可见时 对用户来说,他们的整个碎片可能被销毁,只保留了 该片段的保存状态。这使得寻呼机可以保留很多信息 与。相比,与每个访问页面关联的内存更少 FragmentPagerAdapter的代价是潜在的更多的开销时

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

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

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

134865 次浏览

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

FragmentStatePagerAdapter:

  • with FragmentStatePagerAdapter,你不需要的片段是 摧毁。事务提交时完全删除

    . fragment from你的活动的FragmentManager
  • FragmentStatePagerAdapter中的状态来自于它 将保存你的片段的BundlesavedInstanceState当 它被摧毁了。当用户导航回来时,新的片段将是

FragmentPagerAdapter:

    通过比较,FragmentPagerAdapter不做这类事情。当 不再需要这个片段。FragmentPagerAdapter调用

    . {/p> . 销毁片段的视图,但保留片段的实例 活在FragmentManager。创建的片段 FragmentPagerAdapter永远不会被销毁

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

在文档或本页的回答中没有明确说明的事情(即使由@Naruto暗示)是,如果片段中的数据发生变化,FragmentPagerAdapter将不会更新片段,因为它将片段保存在内存中。

所以即使你有有限数量的片段显示,如果你想要能够刷新你的片段(例如你重新运行查询来更新片段中的listView),你需要使用FragmentStatePagerAdapter。

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

FragmentStatePagerAdapter =在ViewPager中容纳大量的片段。当片段对用户不可见时,这个适配器会销毁它,并且只保留片段的savedInstanceState以供进一步使用。在动态片段的情况下,这样可以使用较少的内存并提供更好的性能。

下面是ViewPager中每个片段的日志生命周期,其中有4个片段和offscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

转到Fragment1(启动活动)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

去Fragment2

Fragment3: onCreateView
Fragment3: onStart

进入Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart

去Fragment4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

转到Fragment1(启动活动)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

去Fragment2

Fragment3: onCreateView
Fragment3: onStart

进入Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart

去Fragment4

Fragment2: onStop
Fragment2: onDestroyView

结论:当Fragment被克服时,FragmentStatePagerAdapter调用onDestroy,而FragmentPagerAdapter不调用。

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

offscreenPageLimit例子:

如果我们去Fragment3,它破坏Fragment1(或Fragment5如果有),因为offscreenPageLimit = 1。如果我们设置offscreenPageLimit > 1,它会不会 destroy.
如果在本例中,我们设置了offscreenPageLimit=4,则使用FragmentStatePagerAdapterFragmentPagerAdapter之间没有区别,因为当我们更改tab

时,Fragment从不调用onDestroyViewonDestroy

Github demo here

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

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

医生说:

有两种类型的标准pageradapter管理每个片段的生命周期:FragmentPagerAdapter和FragmentStatePagerAdapter。它们都能很好地处理片段,但它们更适合不同的场景:

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

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

不知道技术细节,但根据我的经验:
如果你试图在一个片段中的viewPager中使用FragmentStatePagerAdapter,那么你的子片段的选项菜单可能会被打乱(或者根本不显示),如果你导航到另一个页面并返回。但它将适用于FragmentPagerAdapter
据我所知,在用户单击一个选项卡之前,子片段的onCreateOptionsMenu没有被调用。这可能是故意的,但对我来说是一场噩梦

我在无望的搜索中偶然发现了一些页面:
https://issuetracker.google.com/issues/37092407
Viewpager中片段的选项菜单显示彼此的按钮
嵌套片段在viewpager与不同的菜单 < / p >

PS:任何使用FragmentStatePagerAdapter的优雅解决方案或建议都是受欢迎的