【问题标题】:Dynamic Fragment recreation and setRetainInstance(true)动态片段重新创建和 setRetainInstance(true)
【发布时间】:2014-07-07 21:10:57
【问题描述】:

我不完全了解如何重新创建活动及其片段。

想象以下场景:您有一个数据库,活动读取此DB 和一个片段,如果活动对DB 的查询有一些数据,则会创建一个片段。如果DB 为空,片段的onCreateView 将导致异常。

现在想象一下,我们将应用程序移到后台一段时间,并且 Activity 被破坏了。此外,DB 更改并变为空。

如何重建这个结构?活动启动并理解不需要片段,所以一切都很好,或者片段被重新创建,因为它已经被创建了? setRetainInstance(true/false) 对这个过程有影响吗?

让它变得更复杂:我们有几个片段,其中一个决定是否应该以类似的方式创建另一个。碎片娱乐的顺序是什么?是某种竞争条件还是预定义的顺序?

最后,我们如何防止或控制片段的重新创建?我想我有一种情况,有时片段不是在正确的时间重新创建的。如何修复这样的架构?只需使用onStop() 删除片段?

【问题讨论】:

  • 快速说明:你永远不应该自己调用onStop()——这将由Android运行时调用。你可以打电话给finish()
  • @user184994,是的,很清楚。我只需将mFragmentManager.beginTransaction().remove(mFragment).commit()移动到OnStop(),片段就会自动及时删除。

标签: android dynamic android-fragments


【解决方案1】:

片段的生命周期与 Activity 的生命周期相关联。来自 Android 文档:

已停止

片段不可见。主机活动已停止,或者片段已从活动中删除但已添加到后台堆栈。已停止的片段仍然存在(系统保留所有状态和成员信息)。但是,它不再对用户可见,并且如果 Activity 被杀死,它将被杀死。

当Activity被销毁时,会调用onCreate()方法重新创建Activity。这意味着如果底层数据库发生了变化,Activity 可以决定不启动 Fragment。

您可以阅读有关 Fragment 生命周期 here 和 Activity 生命周期 here 的更多信息。

【讨论】:

  • 这是否意味着,当使用 setRetainInstance(true) 时,只有当 Activity 想要使用该 Fragment 时才会重新创建 Fragment?
  • 如果你设置setRetainInstance为true,fragment实际上不会被销毁,即使Activity被销毁。它不需要重新创建,因为它仍然存在
【解决方案2】:

我不完全了解活动及其片段的情况 重新创建。

首先,非常重要的是要非常清楚 Activity/Fragments 的生命周期在 Android 中是如何工作的。在这里,我链接了恕我直言,关于该主题的最完整图表(甚至比官方图表还多):

http://staticfree.info/~steve/complete_android_fragment_lifecycle.svg

想象以下场景:你有一个数据库,活动阅读 这个数据库和一个片段,如果活动的查询将被创建 到 DB 有一些数据。如果 DB 为空,片段的 onCreateView 将 导致异常。现在想象我们将应用程序移到后台 而活动被破坏了。此外,数据库更改并获取 空。

这种操作,如读取或写入数据库(或连接到 Web 服务或更多)被视为 I/O,应在后台进行适当管理。我不知道您的具体细节,但在您的示例中,您可以使用 CursorLoader。 Android 文档说明如下:

查询 ContentResolver 并返回 Cursor 的加载程序。这 类以标准方式实现 Loader 协议以进行查询 游标,建立在 AsyncTaskLoader 上以在 asyncTaskLoader 上执行游标查询 后台线程,这样它就不会阻塞应用程序的 UI。

还有

如果 DB 为空,片段的 onCreateView 将导致异常。

如果 DB 为空,则片段不应导致异常(任何),例如,如果您使用 CursorLoader,它将最终获得一个包含 0 个条目的 Cursor。稍后(这又取决于您的实现),如果您更新数据库,您可以执行新的 CursorLoader 请求以使用新数据获取刷新的 Cursor(旋转设备时同样适用)。

Wolfram Rittmeyer 编写的 How to use LoardersAlex Lockwood 编写的 Life before Loaders 两个很好的教程更深入地讨论了 CursorLoader

Activity 启动并理解该片段是不需要的,所以 一切正常,否则无论如何都会重新创建片段,因为它 已经创建了吗? setRetainInstance(true/false) 是否有 对这个过程有影响吗?

活动是一个“愚蠢”的组件,它本身并不知道片段是什么(这并不完全正确,因为活动的实现知道片段)。但是,看在好人的份上,这实际上取决于您尝试做什么。如果您的活动中有一个片段,它将最终被重新创建。您必须留意两个类才能了解它是如何工作的:

最后,我们如何防止或控制片段的重新创建?一世 猜我有一种情况,有时会重新创建片段而不是 在正确的时间。如何修复这样的架构?简单地 使用 onStop() 删除片段?

永远不要自己搞乱生命周期事件,这是由 android 运行时正确管理的。

【讨论】:

  • 感谢您的链接,我知道了。你说 Activity 很笨,但是,我明白 Activity 有责任正确管理它的 Fragment,严格控制何时创建、重新创建特定的 Fragment 等等。
  • 是的,Android 管理片段恢复(更准确地说是FragmentManagerImpl.java),像 onActivityResult 这样的事件会自动转发到片段(你可以在FragmentActivity.java 的代码中看到它)但是当你把活动中的片段。如果您的代码中没有片段,则它与它无关。我正在考虑一个用片段做事的示例项目(超出基础,但我现在不记得一个确切的:/)。
  • 我想到的唯一例子是 ioSched 2013 的源代码,但它是一个完整的应用程序……但它确实使用了很多片段、游标加载器等等!链接:github.com/skyisle/iosched
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
相关资源
最近更新 更多