在阅读了介绍性的Android编程书之后,我想改变示例应用程序,以巩固我对一些未真正涵盖的主题的理解。在进行更改时,我犯了一个错误,但我很好奇为什么错误在某些情况下有效但在其他情况下却没有。
应用程序中的活动在Hashtable<Integer, Question>
中存储一系列问题,其中Question是一个包含int和两个字符串的小类。最初编写时,活动会在每onCreate()
个{@ 1}}上从服务器下载问题,因此我希望实施onSaveInstanceState()
以防止一些冗余下载。 onSaveInstanceState()
使用putSerializable()
将Hashtable保存到Bundle中。
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// mQuestions is a member variable of
// type Hashtable<Integer, Question>
if (mQuestions != null && mQuestions.size() > 0) {
outState.putSerializable(SAVED_QUESTIONS, mQuestions);
}
}
在我知道Parcelable是什么或如何实现之前,它完全适用于屏幕方向的变化。我只知道当我按下模拟器的主页键和应用程序静默时出现问题,无法在没有LogCat输出的情况下崩溃。堆栈跟踪让我查找Parcelable并使Question实现它。
我的问题不是我做错了什么。问题是:当问题类没有实现Parcelable时,为什么应用程序只在按Home而不是屏幕方向更改时崩溃?
答案 0 :(得分:2)
据我所知,Android在配置更改后重新创建活动时不会序列化实例状态。这就是你的代码有效的原因。持久对象不需要是可分解的,因为它们只存在于内存中。
这看起来像是一种优化。 Android知道在这种情况下不会终止进程,也不需要将实例状态保存到文件中。 (理论上,这个过程可以在配置更改期间终止,我真的不知道Android如何解决这个问题。)
但是当用户按下Home键时,您的应用程序将变为背景。并且在内存不足的情况下可以终止其进程。 Android需要将活动的状态保存到文件中,以便将来能够恢复您的应用及其活动。在这种情况下,实例状态实际上是序列化的并保存到持久存储中。这就是你的代码不起作用的原因。
进程终止可以随时发生,因此您不能依赖某些实现细节。只需将实例状态设为可分区或可序列化,您就不会再遇到此问题了。
答案 1 :(得分:1)
引用史蒂夫·莫斯利
根据http://developer.android.com/reference/android/app/Activity.html中有关活动状态的文档,请注意 不 安全使用onSaveInstanceState
和onRestoreInstanceState
该文件陈述(在“活动生命周期”部分):
请注意保存很重要 相反,
onPause()
中的持久数据onSaveInstanceState(Bundle)
的 因为后者不属于 生命周期回调,所以不会 在所描述的每种情况下都会被呼 在其文档中。
换句话说,请将保存/恢复代码改为onPause()
和onResume()
!
答案 2 :(得分:0)
应用程序没有崩溃。当用户单击Home键时,它就会被关闭。这就是LogCat没有输出的原因。
在Activity.onDestroy()中设置断点以确认这一点。如果我正确onDestroy()将被调用但onSaveInstanceState()不会被调用,因为onSaveInstanceState()仅在应用程序处于后台状态时被调用,而不是在它被关闭时被调用。
如果您需要在关机时保存应用程序状态,请将代码放在onDestroy()中并将其保存为比Bundle更持久的内容。
百里