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

标签 android android-fragments android-viewpager android-fragmentactivity

我一直在努力找出在 FragmentActivity 中正确管理 Fragment 的方法。与 ViewPager是。在我详细介绍之前,我面临的问题的快速摘要如下:

我有一个 FragmentActivityViewPager . ViewPager使用自定义但非常简单 FragmentPagerAdapter .每个FragmentViewPager包含一个 ExpandableListView .我还有一个名为“刷新”的操作栏按钮。现在,让我们假设 ViewPager只有一个 Fragment . Activity 已创建,FragmentExpandableListView人口稠密(到目前为止一切顺利)。当点击刷新按钮时,FragmentActivity内的处理方法迭代 Fragments 的列表分配给 FragmentPagerAdapter 并调用 refresh()在每个 Fragment填充其 ListView。但是,当设备的方向发生变化(例如从纵向变为横向)时,Activity 会重新创建, fragment 也会重新创建。现在单击“刷新”按钮将遍历未初始化的 Fragments .

我知道我很含糊,尤其是没有示例代码,但请耐心等待。我从应用程序/Activity 的开始跟踪问题和方法调用如下:

  • FragmentActivity.onCreate()
  • FragmentActivity.setContentView()
  • FragmentActivity.createPagerFragments() <-- 这将创建一个 Fragment ArrayList 并将它们分配给一个新的 FragmentPagerAdapter,而后者又分配给 ViewPager。
  • Fragment.onAttach()
  • Fragment.onCreate() <-- 这里没什么特别的,只是调用了 super 方法。
  • Fragment.onCreateView() <-- 这里也没什么特别的,只是夸大了布局
  • Fragment.onActivityCreated() <-- 这里也没有。
  • << 一切都好,这里的方向改变了 >>
  • FragmentActivity.onCreate()
  • Fragment.onAttach()
  • Fragment.onCreate()
  • FragmentActivity.setContentView()
  • FragmentActivity.createPagerFragments()
  • Fragment.onCreateView()
  • Fragment.onActivityCreated()
  • << 点击刷新按钮 >>
  • FragmentActivity.refresh() <-- 迭代 #13 中新创建的 Fragments(不是这些由 Android 开发的!)。
  • << 崩溃:Fragment 中 mExpandableListView 的 NullPointerException。 >>

  • 因此,在我看来,问题如下:
    当 Android 重新创建 FragmentActivity和它的 Views屏幕方向改变后(调用上面的#9-15),它会创建新的 Fragment状态恢复到原始状态的对象。但是,这些似乎完全由 FragmentManager 管理。 ,而不是通过 FragmentPagerAdapter .相比之下,当FragmentPagerAdapterFragments 一起重新创建在 Activity 的onCreate方法(见调用#13)Fragments分配给适配器的永远不会有他们的 Fragment.onCreate()Fragment.onCreateView()方法调用。因此,当调用 refresh() 方法时(参见 #17),该方法将迭代这些 Fragments尚未初始化的。因此,当他们尝试填充 ExpandableListView 时, View 的实例变量是 NULL .这是可以预料的,因为实例变量仅在 Fragment.onCreateView() 中分配永远不会被调用的方法 Fragments .

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

    我希望我已经清楚地描述了这个问题,我没有提供示例代码的原因是因为问题(可以看出)不是来自代码本身,而是来自相当不正确(似乎)的 Fragments 重新创建而不是重复使用。但是如果需要,我可以给你示例代码,我只是通过这种方式会更清楚。

    谢谢!

    最佳答案

    阅读内容很多,但在阅读了介绍和问题并体验了 FragmentStatePagerAdapter(类似于 FragmentPagerAdapter)之后,我可以告诉你:

    旋转后,您的适配器将自动连接旧 fragment 。因此,虽然正在重新创建 Activity 创建适配器,但 FragmentManager,它是全局的,它的实例保留 Activity 的重新创建将检测到新的 FragmentStatePagerAdapter 与相同的 ViewPager 组合并请求相同的 Fragment,并将简单地从 Fragment 的 BackStack 中获取它们。

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

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

    我希望它有所帮助。

    关于ViewPager 和 FragmentPagerAdapter 中 Fragment 的 Android 生命周期管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20355127/

    相关文章:

    android - 查看页面 : override getItemPosition(Object object) method

    java - 如何防止ViewPager中相邻选项卡的自动调用?

    java - Eclipse:创建两个共享文件的项目

    Android 自定义适配器 - 不会返回 View ?

    android - 将 fragment 部分移出屏幕

    android - fragment 内 fragment 中的上下文菜单(ActionMode)

    android - 不同大小的图像不适合 viewpager

    Android Mp 图表设置日期的自定义 X 轴

    android - 是否可以在移动网络浏览器中启用 WebKit JavaScript Inspector?

    安卓:设置初始保存状态