繁体   English   中英

ViewPager和FragmentPagerAdapter中的片段的Android生命周期管理

[英]Android Lifecycle management of Fragments within ViewPager and FragmentPagerAdapter

我一直在努力找出使用ViewPagerFragmentActivity对Fragment的正确管理是什么。 在详细介绍之前,我将简要概述一下我所面临的问题:

我有一个带有ViewPagerFragmentActivity ViewPager使用自定义但非常简单的FragmentPagerAdapter ViewPager每个Fragment都包含一个ExpandableListView 我还有一个名为“刷新”的操作栏按钮。 现在,让我们假设ViewPager只有一个Fragment 创建活动,并填充FragmentExpandableListView (到目前为止非常好)。 单击“刷新”按钮时, FragmentActivity的处理方法将遍历分配给FragmentPagerAdapter的Fragments列表,并在每个Fragment上调用refresh()以填充其ListView。 但是,当设备的方向发生变化(例如,从纵向变为横向)时,将重新创建“活动”,并且也会重新创建片段。 现在单击“刷新”按钮将遍历未初始化的Fragments

我知道我很模糊,尤其是没有示例代码时,但是请耐心等待。 从应用程序/活动的开始,我已经跟踪了以下问题和方法调用:

  1. FragmentActivity.onCreate()
  2. FragmentActivity.setContentView()
  3. FragmentActivity.createPagerFragments() <-这将创建一个ArrayList of Fragments,并将它们分配给新的FragmentPagerAdapter,后者又分配给ViewPager。
  4. Fragment.onAttach()
  5. Fragment.onCreate() <-在这里没什么特别的,只是调用super方法。
  6. Fragment.onCreateView() <-这里也没有什么特别的,只是扩大了布局
  7. Fragment.onActivityCreated() <-在这里也没有。
  8. <<所有的好,方向在这里改变>>
  9. FragmentActivity.onCreate()
  10. Fragment.onAttach()
  11. Fragment.onCreate()
  12. FragmentActivity.setContentView()
  13. FragmentActivity.createPagerFragments()
  14. Fragment.onCreateView()
  15. Fragment.onActivityCreated()
  16. <<单击刷新按钮>>
  17. FragmentActivity.refresh() <-迭代#13上新创建的片段(Android不能使用这些片段!)。
  18. <<崩溃:Fragment中的mExpandableListView的NullPointerException。 >>

因此,我所看到的问题如下:当Android在更改屏幕方向后重新创建FragmentActivity及其Views (上面的调用#9-15),它将创建新的Fragment对象,其状态恢复为原来的。 但是,这些似乎完全由FragmentManager而不是FragmentPagerAdapter 相反,当FragmentPagerAdapter与沿重新创建Fragments在活动的onCreate方法(见调用#13)的Fragments是那些获得分配给适配器永远不会有自己的Fragment.onCreate()Fragment.onCreateView()称为在方法所有。 因此,当调用refresh()方法(请参阅#17)时,该方法将对这些尚未初始化的Fragments迭代。 因此,当他们尝试填充ExpandableListView ,视图的实例变量为NULL 这是可以预期的,因为实例变量仅在Fragment.onCreateView()方法中分配,而该从来没有在这些Fragments上调用。

所以我的问题是:如何改变屏幕方向后如何正确使用重新创建的(由Android生成的) Fragments ,以避免创建未初始化的Fragments 我需要对它们有一个有效的引用,以便调用按需填充它们的refresh()方法。 理想情况下,也应该将它们也分配给FragmentPagerAdapter

我希望我已经清楚地描述了这个问题,而我之所以没有提供示例代码,是因为问题(可以看出)不是源于代码本身,而是源于片段的相当不正确(重新移植)的创建而不是重复使用。 但是如果需要,我可以给您示例代码,通过这种方式我会更清楚。

谢谢!

要阅读很多东西,但是在阅读完简介和问题并具有FragmentStatePagerAdapter的经验之后,我类似于FragmentPagerAdapter可以告诉您:

旋转后,适配器将自动附着旧碎片。 因此看来,尽管正在重新创建活动创建适配器,但全局的FragmentManager和实例保留活动的重新创建将检测到新的FragmentStatePagerAdapter与相同的ViewPager组合在一起并请求相同的Fragments,并且只需从Fragment的BackStack中获取它们即可。

作为Fragments的设计者,您可以通过继续调用Fragment.onAttach()和Fragment.onDetach()来注意到此行为。 发生onAttach()时,要么创建您的Fragment,要么在旋转后重新使用它。 您应该能够通过使用回调onRestoreRnstanceState()来区分Fragment是旋转的。

您将在日志中同时看到许多onCreate()和其他状态日志,因为FragmentStatePagerAdapter总是获取/创建最少3个片段(除非您将它们设置为2或1),因此在屏幕旋转后,还会从中重新附加3个片段后栈。

希望对您有所帮助。

我相信这个问题 ,有关检索从ViewPager当前片段,会帮助你。 如前所述,片段由Fragment(State)PagerAdapter和NOT Activity或Fragment的生命周期管理。

  • 第一次创建活动时, getItem方法将返回片段。 即使重新创建活动,每个片段仅调用一次此方法。
  • 随后,片段由instantiateItem方法返回。 很可能是在这里,您需要掌握片段并调用其刷新方法。

如何将其添加到清单中的“活动代码”中:

android:configChanges="orientation"

或API 13以上的版本

android:configChanges="orientation|screenSize" 

因此当它改变方向时,它不会重新创建您的片段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM