究竟何时调用onSaveInstanceState()和onRestoreInstanceState()?


102

下图(来自官方文档)描述了Android活动的众所周知的生命周期

在此处输入图片说明

另一方面,当活动被系统销毁时(例如,由于需要回收内存),活动状态有时会通过方法和自动保存和恢复,如下图所示(也来自官方文档):onSaveInstanceState()onRestoreInstanceState()

在此处输入图片说明

我知道 onSaveInstanceState()不是总叫当活动即将被销毁。例如,如果由于用户按下“后退”按钮而将其销毁,则不会保留活动状态。但是在状态保存,恢复和onSaveInstanceState()/ onRestoreInstanceState()或被调用的情况下,究竟何时调用它们

例如,根据以上附图,onRestoreInstanceState()可能在之前onStart()或之后被调用,onStart()但是在之前onResume()或之后被调用onResume()。同样,存在多种可能性onSaveInstanceState()。那么什么时候确切地称呼他们呢?

理想情况下,我希望看到一张显示活动生命周期状态和save / restore方法(如果存在)的组合图


从Android官方文档中获得了最终答案,即onPause()和onStop()之间调用的onSaveInstanceState()。
Rishi

1
@Rishi您能否提供该文件的链接?
路易斯·门多


阅读“保存您的活动状态”段落
-Rishi

我是否正确,请澄清
Rishi

Answers:


107

根据文档

void onRestoreInstanceState(捆绑的saveInstanceState)

此方法在onStart()和之间调用onPostCreate(Bundle)

void onSaveInstanceState(捆绑输出状态)

如果调用,此方法将在onStop()之后针对以Build.VERSION_CODES.P开头的平台为目标的应用程序发生。对于面向较早平台版本的应用程序,此方法将在onStop()之前发生,并且不能保证它会在onPause()之前还是之后发生。


1
谢谢。您能否提供文档的链接?
路易斯·门多

在这里,我也认为onStart()和onPostCreate()之间没有其他内容,因此onRestoreInstanceState()在链中定义良好。
史蒂夫M

非常感谢。这澄清了问题
Luis Mendo 2013年

1
@SteveM“无法保证它会在onPause()之前还是之后发生”这是否意味着如果我们尝试访问视图(以获取一些值来保存,例如来自列表视图的索引),我们可能会遇到NullPointerExceptions?
Tiago

3
然后,建议什么,将数据结构保存在onPause中,然后将其还原到onResume中,而不是onSaveInstanceState和onRestoreInstanceState中?
2015年

18

按照 doc1doc2

onSaveInstanceState

在Honeycomb之前,直到活动被暂停才被认为是可杀死的,这意味着onSaveInstanceState()在onPause()之前被调用。但是,从Honeycomb开始,仅在活动被停止后才认为它们是可杀死的,这意味着onSaveInstanceState()现在将在onStop()之前而不是在onPause()之前被调用。

onRestoreInstanceState

从先前保存的状态重新初始化活动时,在onStart()和onPostCreate(Bundle)之间调用此方法


喜欢您描述不同Android版本上的场景的方式
Jimit Patel

14

除了已经发布的答案之外,Android P还进行了微妙的更改,即:

void onSaveInstanceState(Bundle outState)

如果调用,此方法将在针对以P开头的平台的应用程序之后 发生。对于面向较早平台版本的应用程序,此方法将在此方法之前发生,并且不能保证它会在此之前还是之后发生。onStop()onStop()onPause()

资料来源:docs

至于为什么要引入此更改,以下是答案:

...因此应用程序可以安全地执行片段事务,onStop()并且以后可以保存持久状态。

资料来源:docs


嗨,很好的评论。您知道以P为目标但在较低api上运行的应用的表现如何吗?与定位较低api的应用相同,还是在api之间保持一致并保持“ targeting api”行为?
Filipkowicz

@Filipkowicz,Do you know how will behave app that target P but runs on lower api?只要该应用在M上运行,那么该设备所具有的Android版本就不会包含P中引入的更改,这意味着无论您是否指定了目标,P都不会看到对于pre-P设备而言是不同的。希望这能回答您的问题。
azizbekian

今天,我在阅读完此答案后感到非常放松,因为我正在Udacity上进行android免费课程,而它们仍然具有旧版本的教程,该课程在第5课练习8中指出,onStop和onDestroy方法不应位于显示的textView。但是我不知道那是针对较旧版本的android的,并且我正在android pie上运行我的应用程序,并且在我的textView中获取了onStop方法。非常感谢。终于感觉不错。
桑杜

6

这是onSaveInstanceState(Bundle)的附加信息

来自docs

请勿将此方法与活动生命周期回调(例如onPause())混淆,后者在活动放置在后台或销毁过程中总是被调用,而onStop()在销毁之前被调用。何时调用onPause()和onStop()而不是使用该方法的一个示例是,当用户从活动B导航回活动A时:无需在B上调用onSaveInstanceState(Bundle),因为该特定实例将永远不会恢复,因此系统避免调用它。在调用onPause()而不是onSaveInstanceState(Bundle)时的一个示例是在活动A之前启动活动B的情况:如果在活动B的生命周期内未将其杀死,则系统可以避免在活动A上调用onSaveInstanceState(Bundle) A的用户界面状态将保持不变。

所以它是..的默认实现

默认实现通过在具有ID的层次结构中的每个视图上调用onSaveInstanceState()并保存当前关注的视图的ID(所有内容均由UI还原)来为您处理大部分UI每个实例状态。 onRestoreInstanceState(Bundle))的默认实现。如果重写此方法以保存未由每个单独的视图捕获的其他信息,则您可能需要调用默认实现,否则准备自己保存每个视图的所有状态。


0
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捆绑包与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);
} 

请问,当调用保存/恢复方法时,该如何回答这个问题?
路易斯·门多
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.