我在SO上发现了许多类似问题的实例,但不幸的是,答案不符合我的要求 .
我有纵向和横向的不同布局,我使用后台堆栈,这两个都阻止我使用 setRetainState()
和使用配置更改例程的技巧 .
我在TextViews中向用户显示某些信息,这些信息不会保存在默认处理程序中 . 仅使用活动编写我的应用程序时,以下工作正常:
TextView vstup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.whatever);
vstup = (TextView)findViewById(R.id.whatever);
/* (...) */
}
@Override
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putCharSequence(App.VSTUP, vstup.getText());
}
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
vstup.setText(state.getCharSequence(App.VSTUP));
}
使用 Fragment
,这仅适用于非常特定的情况 . 具体来说,可怕的破坏是替换片段,将其放入后台堆栈,然后在显示新片段时旋转屏幕 . 根据我的理解,旧片段在被替换时没有接收到对 onSaveInstanceState()
的调用但是以某种方式与 Activity
相关联,并且此方法稍后在其 View
不再存在时被调用,因此将我的任何 TextView
结果查找到 NullPointerException
.
另外,我发现保留对 TextViews
的引用对于 Fragment
来说并不是一个好主意,即使它与 Activity
一样好 . 在这种情况下, onSaveInstanceState()
实际上保存了状态但是如果我在隐藏片段时将屏幕旋转两次,则问题会重新出现,因为它在新实例中没有被调用 onCreateView()
.
我想将 onDestroyView()
中的状态保存到一些 Bundle
类型的成员元素中(它实际上是更多的数据,而不仅仅是一个 TextView
)并将其保存在 onSaveInstanceState()
中,但还有其他缺点 . 首先,如果当前显示片段,则调用这两个函数的顺序是相反的,因此我需要考虑两种不同的情况 . 必须有一个更清洁,更正确的解决方案!
6 回答
要正确保存
Fragment
的实例状态,您应该执行以下操作:1. 在片段中,通过覆盖
onSaveInstanceState()
保存实例状态并在onActivityCreated()
中恢复:2. 和 important point ,在活动中,您必须将片段的实例保存在
onSaveInstanceState()
中并在onCreate()
中恢复 .希望这可以帮助 .
我只想提供我想出的解决方案来处理本文中我从Vasek和devconsole派生的所有案例 . 此解决方案还可以处理特殊情况,当手机不能旋转多次而片段不可见时 .
这是我存储捆绑以供以后使用,因为onCreate和onSaveInstanceState是片段不可见时唯一的调用
由于在特殊旋转情况下不调用destroyView,我们可以确定如果它创建状态我们应该使用它 .
这部分是一样的 .
现在 here 是棘手的部分 . 在我的onActivityCreated方法中,我实例化"myObject"变量,但是onActivity和onCreateView上的旋转不会被调用 . 因此,当方向旋转多次时,myObject在这种情况下将为null . 我通过重复使用onCreate中保存的相同包作为外包来解决这个问题 .
现在,只要您想要恢复状态,只需使用savedState包
这就是我现在使用的方式......它非常复杂,但至少它可以处理所有可能的情况 . 如果有人有兴趣 .
Alternatively ,始终有可能将数据显示在被动
View
中的变量中,并仅使用View
来显示它们,保持两者同步 . 不过,我不认为最后一部分很干净 .在最新的支持库中,这里讨论的解决方案都不再需要 . 您可以使用
FragmentTransaction
随意播放Activity
的片段 . 只需确保您的片段可以使用ID或标记进行标识 .只要您不在每次调用
onCreate()
时尝试重新创建片段,片段就会自动恢复 . 相反,您应检查savedInstanceState
是否为null,并在此情况下查找对创建的片段的旧引用 .这是一个例子:
但请注意,当恢复片段的隐藏状态时,当前存在bug . 如果要在活动中隐藏片段,则需要在这种情况下手动恢复此状态 .
感谢DroidT,我做了这个:
我意识到如果Fragment没有执行onCreateView(),它的视图就不会被实例化 . 因此,如果后堆栈上的片段没有创建其视图,我保存最后存储的状态,否则我使用我想要保存/恢复的数据构建我自己的bundle .
1)扩展这个课程:
2)在你的片段中,你必须有:
3)例如,您可以在onActivityCreated中调用hasSavedState: