FragmentPagerAdapter
和FragmentStatePagerAdapter
之间有什么区别?
关于FragmentPagerAdapter
谷歌的指南说:
此版本的分页器最适合在有大量通常更为静态的片段(如一组选项卡)需要分页时使用。用户访问的每个页面的片段都将保存在内存中,虽然它的视图层次结构在不可见时可能会被破坏。这可能会导致使用大量的内存,因为片段示例可以保持任意数量的状态。对于较大的页面集,请考虑FragmentStatePagerAdapter
。
而关于FragmentStatePagerAdapter
:
此版本的页导航在页面数量较多时更有用,其工作方式更像列表视图。当页面对用户不可见时,它们的整个片段可能会被破坏,仅保持该片段的保存状态。与FragmentPagerAdapter
相比,这允许寻呼机保持与每个被访问的寻呼相关联的少得多的存储器,代价是在得双曲余切值.
所以我只有3个片段。但是它们都是独立的模块,有大量的数据。Fragment1
处理一些数据(用户输入的数据),并通过activity将其传递到Fragment2
,Fragment2
只是一个简单的ListFragment
。Fragment3
也是一个ListFragment
。
"我的问题是“我应该使用哪种适配器?FragmentPagerAdapter
还是FragmentStatePagerAdapter
?
9条答案
按热度按时间ou6hu8tu1#
片段分页器适配器:用户访问的每个页面的片段将被存储在内存中,尽管视图将被破坏。2所以当页面再次可见时,将重新创建视图,但不重新创建片段示例。这可能会导致使用大量内存。当需要在内存中存储整个片段时,应使用FragmentPagerAdapter。FragmentPagerAdapter调用detach(Fragment)而不是remove(Fragment)。
片段状态分页器适配器:当用户看不到片段示例时,除了片段的保存状态外,片段示例将被销毁。这会导致只使用少量内存,并有助于处理更大的数据集。应该在我们必须使用动态片段时使用,如带有小部件的片段,因为它们的数据可以存储在savedInstanceState中,而且即使存在大量片段也不会影响性能。
1mrurvl12#
根据doc:
有两种类型的标准PagerAdapter用于管理每个片段的生命周期:FragmentPagerAdapter和FragmentStatePagerAdapter。这两个适配器都可以很好地处理片段,但它们更适合于不同的情况:
vojdkbi03#
不了解技术细节,但根据我的经验:
如果你试图在一个片段中的viewPager中使用
FragmentStatePagerAdapter
,那么当你导航到另一个页面并返回时,你的子片段的选项菜单可能会混乱(或者根本不显示)。就我所见,
onCreateOptionsMenu
的子片段直到用户点击一个标签才被调用。这可能是有意的,但对我来说是一场噩梦。一些页面我来accros在绝望的搜索:
https://issuetracker.google.com/issues/37092407
OptionsMenu of Fragments in Viewpager showing each other's Buttons
Nested fragments in viewpager with different menus
PS:欢迎使用
FragmentStatePagerAdapter
对这个特定问题提出任何优雅的解决方案或建议arknldoa4#
就像文档中说的那样,可以这样想。如果你要做一个像图书阅读器这样的应用程序,你不会想一次将所有的片段加载到内存中。你会想在用户阅读时加载并销毁
Fragments
。在这种情况下,你将使用FragmentStatePagerAdapter
。如果你只是显示3个“标签”,不包含很多繁重的数据(比如Bitmaps
),那么FragmentPagerAdapter
可能很适合你。另外,请记住,ViewPager
默认会加载3个片段到内存中。你提到的第一个Adapter
可能会破坏View
的层次结构,并在需要时重新加载它,第二个Adapter
只保存Fragment
的状态,并完全破坏它,如果用户随后返回到该页面,则检索该状态。ojsjcaue5#
片段状态分页器适配器:
FragmentStatePagerAdapter
,您不需要的片段将被销毁。提交一个事务以从Activity的FragmentManager
中完全删除该片段。FragmentStatePagerAdapter
中的状态来自于这样一个事实,即当片段被销毁时,它会从savedInstanceState
中保存出片段的Bundle
。当用户向后导航时,新片段将使用片段的状态进行恢复。片段分页器适配器:
FragmentPagerAdapter
不做任何类似的事情。当不再需要片段时,FragmentPagerAdapter
在事务上调用detach(Fragment)
而不是remove(Fragment)
。FragmentManager
中保持活动状态,因此在FragmentPagerAdapter
中创建的fragment永远不会被销毁。q8l4jmvw6#
下面是
ViewPager
中每个片段的日志生命周期,其中包含4个片段和offscreenPageLimit = 1 (default value)
片段状态分页器适配器
转到片段1(启动活动)
转到片段2
转到片段3
转到片段4
片段分页器适配器
转到片段1(启动活动)
转到片段2
转到片段3
转到片段4
结论:当片段被
offscreenPageLimit
克服而FragmentPagerAdapter
未被克服时,FragmentStatePagerAdapter
调用onDestroy
。注意:我认为我们应该将
FragmentStatePagerAdapter
用于包含大量页面的ViewPager
,因为这样会提高性能。offscreenPageLimit
的示例:如果我们转到Fragment3,它将销毁Fragment1(或Fragment5,如果有),因为
offscreenPageLimit = 1
。如果我们设置offscreenPageLimit > 1
,它将不会销毁。如果在本例中,我们设置
offscreenPageLimit=4
,则使用FragmentStatePagerAdapter
或FragmentPagerAdapter
没有区别,因为当我们更改tab时,Fragment从不调用onDestroyView
和onDestroy
Github demo here
inb24sb27#
在文档或本页的答案中没有明确说明的是(即使@Naruto暗示了这一点),如果Fragment中的数据发生变化,
FragmentPagerAdapter
不会更新Fragment,因为它将Fragment保留在内存中。因此,即使要显示的片段数量有限,如果希望能够刷新片段(例如,重新运行查询以更新片段中的listView),也需要使用FragmentStatePagerAdapter。
我的观点是,片段的数量以及它们是否相似并不总是要考虑的关键方面,片段是否是动态的也是关键。
qfe3c7zg8#
FragmentPagerAdapter
存储从适配器获取的先前数据,而FragmentStatePagerAdapter
在每次执行时从适配器获取新值。v8wbuo2f9#
FragmentStatePagerAdapter =在ViewPager中容纳大量片段。由于此适配器会在用户看不到片段时将其销毁,因此只保留片段的savedInstanceState以供将来使用。这种方式使用的内存量较少,并且在动态片段的情况下可提供更好的性能。