无法使用Fragment.setRetainInstance()作为Activity.onRetainNonConfigurationInstance()的替代品

时间:2012-07-21 10:13:24

标签: android android-fragments

根据Android API文档,Activity.onRetainNonConfigurationInstance()已被弃用,转而使用Fragment.setRetainInstance()

但是,我遇到了两种不同的情况,即Fragment.setRetainInstance()似乎不可行。

  1. 如果Fragment包含WebView。根据{{​​3}},您无法跨配置更改重复使用WebView。我想这意味着您需要在屏幕旋转时允许Fragment拆除并重新创建WebView,并使用Diane HackborneWebView.saveState()恢复Web视图状态。

  2. 如果Fragment属于配置更改后不再存在的布局,当FragmentManager尝试恢复Fragment时,它将抛出:

    java.lang.IllegalArgumentException: No view found for id 0x7f060091 for fragment
    

    如果您在横向模式下具有双片段布局,但在纵向模式下具有单片段布局,则会发生这种情况(例如)。当从landscape转换为portrait时,如果setRetainInstance()设置为true,则Fragment都不会被销毁,但是一个片段不再具有要重新附加的有效视图,因此异常。

  3. 因此,如果您正在构建基于Fragment的应用程序,并且需要在配置更改之间保留数据(例如对运行的AsyncTasks的引用),并且您不能使用WebView.restoreState(),那么就没有Fragment.onRetainNonConfigurationInstance(),最好的方法是什么?

1 个答案:

答案 0 :(得分:8)

即使您使用Fragment.setRetainInstance(),片段仍然会拆除其视图并在配置更改后重新创建它。也就是说,onDestroyView()onCreateView()将在该序列中被调用。确保在onDestroyView()中使对WebView的旧引用无效。您不必担心重新使用WebView - 将使用正确的Activity上下文重新创建新的WebView。这有点无关紧要,因为要保存WebView状态,您仍需要调用WebView.saveState(Bundle)中的Fragment.onSaveInstanceState(Bundle)WebView.restoreState(Bundle)中的Fragment.onViewCreated(Bundle)。这只意味着Fragment.setRetainInstance()仍然与WebView的使用兼容。

您提供的关于视图容器不再存在于另一个方向的示例意味着您不需要保留任何数据 - 在屏幕旋转后根本不会使用该片段。

在任何情况下,不是让单个Fragment处理UI和AsyncTask加载,而是可以将它们分成两个片段 - 具有AsyncTask的片段根本不需要附加到视图层次结构中,并且可以设置成为一个保留的实例。这简化了您的顾虑,并使建筑更清洁。当AsyncTask完成时,您需要回调UI片段以传递结果(例如findFragmentById / Tag,setTargetFragment,自定义侦听器......)。管理AsyncTask的片段需要能够在轮换后检索对UI片段的新实例的引用。