FragmentPagerAdapter和FragmentStatePagerAdapter有什么区别?

Ale*_*tov 357 android android-fragments android-viewpager fragmentpageradapter fragmentstatepageradapter

FragmentPagerAdapter和之间有什么区别FragmentStatePagerAdapter

关于FragmentPagerAdapterGoogle的指南说:

此版本的寻呼机最适合在有少量通常更多静态片段进行分页时使用,例如一组选项卡.用户访问的每个页面的片段将保留在内存中,但其视图层次结构可能在不可见时被销毁.这可能导致使用大量内存,因为片段实例可以保持任意数量的状态.对于较大的页面集,请考虑FragmentStatePagerAdapter.

关于FragmentStatePagerAdapter:

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

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

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

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

Emm*_*uel 285

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

  • @Tomasz`FragmentPagerAdapter`的优点是片段之间的切换可以更快,因为实际的`Fragment`对象不需要每次都重建.另一方面,这将最终使用更多的内存将片段对象保存在内存中. (3认同)
  • @AlexMomotov片段布局中的视图与FragmentStatePagerAdapter的选择无关.这里的问题是将被分页的碎片数量. (2认同)

Luf*_*ffy 125

  • FragmentPagerAdapter将整个片段存储在内存中,如果使用大量片段,可能会增加内存开销 ViewPager.

  • 相反,它的兄弟FragmentStatePagerAdapter只存储片段的savedInstanceState,并在失去焦点时销毁所有片段.

  • 因此,FragmentStatePagerAdapter当我们必须使用动态片段(如带有小部件的片段)时,应该使用它们,因为它们的数据可以存储在savedInstanceState.中.即使存在大量片段,它也不会影响性能.

  • 相反,FragmentPagerAdapter当我们需要将整个片段存储在内存中时,应该使用它的兄弟.

  • 当我说整个片段保存在内存中意味着,它的实例不会被破坏并且会产生内存开销.因此建议FragmentPagerAdapter仅在片段数量较少时使用ViewPager.

  • 如果片段是静态的,那将会更好,因为它们不会有大量的实例存储的对象.

更详细一点,

FragmentStatePagerAdapter:

  • with FragmentStatePagerAdapter,您的不需要的片段被销毁.一个事务被提交以从您的活动中完全删除该片段FragmentManager.

  • 状态FragmentStatePagerAdapter来自这样一个事实:它会在你的片段被销毁时将其保存下来Bundle.savedInstanceState当用户导航回来时,新片段将使用片段的状态进行恢复.

FragmentPagerAdapter:

  • 通过比较FragmentPagerAdapter没有做任何事情.当片段不再需要时.FragmentPagerAdapter调用 detach(Fragment)事务而不是remove(Fragment).

  • 这破坏了片段的视图,但是片段的实例仍然存在于FragmentManager.so中创建的片段 FragmentPagerAdapter永远不会被破坏.

  • @Tomek:如果下一个片段已经被实例化(即FragmentPagerAdapter),当你滑动它时它就可以渲染了,所以滑动动画会更顺畅.使用FragmentStatePagerAdapter,下一个片段实例可能不存在,直到你滑动它,如果它是一个很难创建的大片段,你可能会在动画中看到一个口吃.这是性能与内存消耗的问题. (4认同)
  • 为什么你有2个答案? (2认同)
  • @Jared Burrows bcoz 一个是 _AnswerText_,它适用于小型和静态的答案,另一个是 *AnswerStateText*,适用于更大的动态答案 (2认同)

Pha*_*inh 41

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

FragmentStatePagerAdapter

转到Fragment1(启动活动)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
Run Code Online (Sandbox Code Playgroud)

转到Fragment2

Fragment3: onCreateView
Fragment3: onStart
Run Code Online (Sandbox Code Playgroud)

转到Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart
Run Code Online (Sandbox Code Playgroud)

转到Fragment4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
Run Code Online (Sandbox Code Playgroud)

FragmentPagerAdapter

转到Fragment1(启动活动)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart
Run Code Online (Sandbox Code Playgroud)

转到Fragment2

Fragment3: onCreateView
Fragment3: onStart
Run Code Online (Sandbox Code Playgroud)

转到Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart
Run Code Online (Sandbox Code Playgroud)

转到Fragment4

Fragment2: onStop
Fragment2: onDestroyView
Run Code Online (Sandbox Code Playgroud)

结论:当片段被克服时FragmentStatePagerAdapter调用而不是. onDestroyoffscreenPageLimitFragmentPagerAdapter

:我觉得应该用FragmentStatePagerAdapterViewPager,因为它会很好的表现,其有很多页.

示例offscreenPageLimit:

如果我们去Fragment3,它破坏Fragment1(或Fragment5,如果有)因为offscreenPageLimit = 1.如果我们设置offscreenPageLimit > 1不会破坏.
如果在这个例子中,我们设置offscreenPageLimit=4,使用之间没有区别,FragmentStatePagerAdapter或者FragmentPagerAdapter因为Fragment从不调用onDestroyViewonDestroy我们更改选项卡

Github演示在这里


JDe*_*ais 37

在文档或本页面的答案中没有明确说明的内容(即使@Naruto暗示),FragmentPagerAdapter如果Fragment中的数据发生变化,则不会更新Fragments,因为它会将Fragment保留在内存中.

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

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


小智 14

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