究竟何时调用 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()?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery.ajax() 成功/失败回调何时调用?

UIApplicationLaunchOptionsURLKey 究竟何时被填充?

Android Fragment 和方向更改导致:IllegalStateException: Can not perform this action after onSaveInstanceStat

在 x86 软件中断期间,究竟何时进行上下文切换?

究竟啥是 getattr() 以及如何使用它?

Android-onSaveInstanceState方法啥时候被调用