究竟何时调用 onSaveInstanceState() 和 onRestoreInstanceState()?
Posted
技术标签:
【中文标题】究竟何时调用 onSaveInstanceState() 和 onRestoreInstanceState()?【英文标题】:When exactly are onSaveInstanceState() and onRestoreInstanceState() called? 【发布时间】:2014-01-16 21:12:00 【问题描述】:下图(来自the official doc)描述了众所周知的android Activity 生命周期:
另一方面,当activity被系统销毁时(例如需要回收内存),activity的状态有时会通过方法自动保存和恢复 onSaveInstanceState()
和onRestoreInstanceState()
,如下图所示(也来自the official doc):
当一个活动即将被销毁时,我知道onSaveInstanceState()
是not always called。例如,如果它因为用户按下了“返回”按钮而被销毁,则不会保留活动状态。但是在状态 保存和恢复,onSaveInstanceState()
/ onRestoreInstanceState()
被调用的情况下,它们究竟是什么时候被调用的?
例如,根据上面的数字,onRestoreInstanceState()
可能在onStart()
之前调用,或者在onStart()
之后但在onResume()
之前,或者在onResume()
之后调用。同样,onSaveInstanceState()
也存在几种可能性。那么它们究竟是什么时候调用的呢?
理想情况下,我希望看到一个显示活动生命周期状态和保存/恢复方法的组合图(如果存在)。
【问题讨论】:
从Android官方文档中得到了最终答案,onSaveInstanceState()在onPause()和onStop()之间调用。 @Rishi 能否提供该文档的链接? developer.android.com/guide/components/activities/… read Save your activity state Paragraph there 我是否正确,请澄清 【参考方案1】:根据documentation:
void onRestoreInstanceState (Bundle savedInstanceState)
此方法在
onStart()
和onPostCreate(Bundle)
之间调用。void onSaveInstanceState (Bundle outState)
如果调用,此方法将在 onStop() 之后针对以 Build.VERSION_CODES.P 开头的平台的应用程序发生。对于面向早期平台版本的应用程序,此方法将在 onStop() 之前发生,并且不能保证它是在 onPause() 之前还是之后发生。
【讨论】:
谢谢。您能否提供文档的链接? 你去吧,我也不认为在onStart()和onPostCreate()之间还有什么,所以onRestoreInstanceState()在链中定义得很好。 非常感谢。这澄清了问题 @SteveM "无法保证它是否会在 onPause() 之前或之后发生" 这是否意味着如果我们尝试访问视图(以获取一些要保存的值,例如来自listview) 我们可能会遇到 NullPointerExceptions? 那么,有什么推荐的,在 onPause 中保存数据结构,在 onResume 中恢复,而不是在 onSaveInstanceState 和 onRestoreInstanceState 中?【参考方案2】:根据doc1 和doc2
onSaveInstanceState
在 Honeycomb 之前,活动直到之后才被认为是可杀死的 已暂停,这意味着 onSaveInstanceState() 在 onPause() 之前立即调用。 然而,从 Honeycomb 开始,活动被认为是 只有在它们被阻止后才能杀死,这意味着 现在将在 onStop() 之前调用 onSaveInstanceState() 而不是 紧接在 onPause() 之前。
onRestoreInstanceState
这个方法在 onStart() 和 onPostCreate(Bundle) 之间被调用,当 活动正在从以前保存的状态重新初始化
【讨论】:
喜欢你描述不同 Android 版本场景的方式【参考方案3】:除了已经发布的答案之外,Android P 中引入了一个微妙的变化,即:
void onSaveInstanceState(Bundle outState)
如果调用,此方法将在之后
onStop()
用于面向以P 开头的平台的应用程序。对于针对早期平台版本的应用程序,此方法将在onStop()
之前发生,并且不能保证它是否会在onPause()
之前或之后发生。
来源:docs
至于为什么要引入这个改动,答案如下:
...所以应用程序可以安全地在
onStop()
中执行片段事务,并且以后能够保存持久状态。
来源:docs
【讨论】:
嗨,很棒的评论。您知道以 P 为目标但在较低 api 上运行的应用程序的行为方式吗?与定位较低 api 的应用相同,或者它将在 api 之间保持一致并保持“定位 api”行为? @Filipkowicz,Do you know how will behave app that target P but runs on lower api?
只要应用程序在 M 上运行,那么此设备所具有的 Android 版本不包含 P 中引入的更改,这意味着无论您已将目标指定为 P
,您都不会看到 pre-P 设备的不同之处。希望这能回答您的问题。
读完这个答案后,我今天感觉很放松,因为我在 Udacity 上做 android 免费课程,他们仍然有旧版本的教程,在第 5 课练习 8 中说明 onStop 和onDestroy 方法不应该出现在显示的 textView 中。但我不知道那是针对旧版本的 android 的,我在 android pie 上运行我的应用程序,并且在我的 textView 中获得了 onStop 方法。太感谢了。终于感觉不错了。【参考方案4】:
这是 onSaveInstanceState(Bundle)
的额外信息from docs
不要将此方法与活动生命周期回调混淆,例如 onPause(),当一个活动被放置时总是被调用 背景或正在销毁的途中,或 onStop() 是 在破坏之前调用。 onPause() 和 onStop() 时的一个示例 被调用,而不是当用户从 活动B到活动A:无需调用 onSaveInstanceState(Bundle) 在 B 上,因为该特定实例将 永远不会被恢复,所以系统避免调用它。一个例子当 onPause() 被调用,而不是 onSaveInstanceState(Bundle) 是什么时候 活动 B 在活动 A 之前启动:系统可能会避免 如果活动 A 没有被杀死,则在活动 A 上调用 onSaveInstanceState(Bundle) 在 B 的生命周期内,从 A 的用户界面状态开始 将保持原样。
所以它是默认实现的..
默认实现会处理每个实例的大部分 UI 通过在每个视图上调用 onSaveInstanceState() 为您状态 具有 id 的层次结构,并通过保存当前的 id 聚焦视图(所有这些都由默认实现恢复 onRestoreInstanceState(Bundle))。如果您将此方法覆盖为 保存每个单独视图未捕获的附加信息,您 可能想要调用默认实现, 否则请准备好自己保存每个视图的所有状态。
【讨论】:
【参考方案5】:String activityState;
@Override
public void onCreate(Bundle savedInstanceState)
// call the super class onCreate to complete the creation of activity like
// the view hierarchy
super.onCreate(savedInstanceState);
// recovering the instance state
if (savedInstanceState != null)
activityState = savedInstanceState.getString(STATE_KEY);
setContentView(R.layout.main_activity);
mTextView = (TextView) findViewById(R.id.text_view);
//只有在之前有保存的实例时才会调用这个回调 保存使用 //onSaveInstanceState()。我们可以在 onCreate() 中恢复一些状态 可选择恢复 // 这里的其他状态,可能在 onStart() 完成后可用。 // savedInstanceState Bundle 与 onCreate() 中使用的相同。
@Override
public void onRestoreInstanceState(Bundle savedInstanceState)
mTextView.setText(savedInstanceState.getString(STATE_KEY));
// invoked when the activity may be temporarily destroyed, save the instance
//state here
//this method will be called before onstop
@Override
public void onSaveInstanceState(Bundle outState)
outState.putString(STATE_KEY, activityState);
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
【讨论】:
请问,这如何回答究竟何时调用保存/恢复方法这个问题?以上是关于究竟何时调用 onSaveInstanceState() 和 onRestoreInstanceState()?的主要内容,如果未能解决你的问题,请参考以下文章
UIApplicationLaunchOptionsURLKey 究竟何时被填充?
Android Fragment 和方向更改导致:IllegalStateException: Can not perform this action after onSaveInstanceStat