142

我正在尝试Activity使用方法onSaveInstanceState()onRestoreInstanceState().

问题是它永远不会进入onRestoreInstanceState()方法。谁能向我解释这是为什么?

4

13 回答 13

194

通常你恢复你的状态在onCreate(). 也可以恢复它onRestoreInstanceState(),但不是很常见。(onRestoreInstanceState()在之后调用onStart(),而onCreate()在之前调用onStart()

使用 put 方法将值存储在onSaveInstanceState()

protected void onSaveInstanceState(Bundle icicle) {
  super.onSaveInstanceState(icicle);
  icicle.putLong("param", value);
}

并恢复中的值onCreate()

public void onCreate(Bundle icicle) {
  if (icicle != null){
    value = icicle.getLong("param");
  }
}
于 2010-11-04T21:18:33.390 回答
153

onRestoreInstanceState()仅在被操作系统杀死后重新创建活动时调用。这种情况发生在:

  • 设备的方向发生变化(您的活动被销毁并重新创建)。
  • 您面前还有另一个活动,并且在某些时候操作系统会终止您的活动以释放内存(例如)。下次您开始活动时,将调用 onRestoreInstanceState()。

相反:如果你在你的活动中并且你点击Back了设备上的按钮,你的活动是完成()ed(即认为它是退出桌面应用程序),下次你启动你的应用程序时它会“重新”启动,即没有保存状态,因为您在点击Back.

其他混淆的来源是,当一个应用失去焦点到另一个应用onSaveInstanceState()时被调用,但是当你导航回你的应用时onRestoreInstanceState()可能不会被调用。这是原始问题中描述的情况,即如果您的活动在其他活动在前面的期间没有被杀死,onRestoreInstanceState()则不会被调用,因为您的活动几乎是“活着的”。

总而言之,如文档中所述onRestoreInstanceState()

大多数实现将简单地使用 onCreate(Bundle) 来恢复它们的状态,但有时在完成所有初始化之后在此处执行此操作或允许子类决定是否使用您的默认实现会很方便。该方法的默认实现会恢复之前被 onSaveInstanceState(Bundle) 冻结的任何视图状态。

正如我所读到的:没有理由重写onRestoreInstanceState(),除非您是子类化Activity并且预计有人会将您的子类子类化。

于 2011-07-17T09:05:50.610 回答
8

您保存的状态onSaveInstanceState()稍后在onCreate()方法调用时可用。所以使用onCreate(及其Bundle参数)来恢复您的活动状态。

于 2010-11-04T11:41:04.560 回答
4

As a workaround, you could store a bundle with the data you want to maintain in the Intent you use to start activity A.

Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);

Activity A would have to pass this back to Activity B. You would retrieve the intent in Activity B's onCreate method.

Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
    intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.

Another idea is to create a repository class to store activity state and have each of your activities reference that class (possible using a singleton structure.) Though, doing so is probably more trouble than it's worth.

于 2014-05-28T15:13:54.597 回答
4

使用保存的实例状态恢复活动 UI 状态的文档中,它被声明为:

您可以选择实现 onRestoreInstanceState(),而不是在 onCreate() 期间恢复状态,系统在 onStart() 方法之后调用它。系统仅在有要恢复的已保存状态时才调用 onRestoreInstanceState() ,因此您无需检查 Bundle 是否为 null

在此处输入图像描述

在此处输入图像描述

IMO,这比在 onCreate 上检查更清晰,更符合单一责任原则。

于 2020-07-06T06:07:45.673 回答
3

主要的是,如果您不存储,onSaveInstanceState()onRestoreInstanceState()不会被调用。restoreInstanceState()这是和之间的主要区别onCreate()。确保你真的储存了一些东西。这很可能是你的问题。

于 2012-10-24T13:03:32.607 回答
3

我发现当另一个 Activity 进入前台时,总是会调用 onSaveInstanceState 。onStop 也是如此。

但是,只有在同时调用了 onCreate 和 onStart 时才调用 onRestoreInstanceState。而且,onCreate 和 onStart 并不总是被调用。

因此,即使 Activity 移动到后台,Android 似乎也不会总是删除状态信息。但是,为了安全起见,它调用生命周期方法来保存状态。因此,如果状态没有被删除,那么 Android 不会调用生命周期方法来恢复状态,因为它们是不需要的。

图 2对此进行了描述。

于 2014-05-14T18:18:35.003 回答
2

我认为这个线程很老了。我只是提到另一种情况,也onSaveInstanceState()将被调用,即当你调用Activity.moveTaskToBack(boolean nonRootActivity).

于 2012-06-27T16:32:04.803 回答
1

如果您使用 和 处理活动的方向更改android:configChanges="orientation|screenSize"onConfigurationChanged(Configuration newConfig)onRestoreInstanceState()不会调用。

于 2015-04-13T10:50:45.720 回答
1

不必总是在 onSaveInstanceState 之后调用 onRestoreInstanceState。

请注意: onRestoreInstanceState 将始终被调用,当活动旋转时(当未处理方向时)或打开您的活动然后打开其他应用程序,以便操作系统从内存中清除您的活动实例。

于 2016-12-07T12:57:04.720 回答
0

就我而言,onRestoreInstanceState在更改设备方向后重建活动时调用。onCreate(Bundle)首先被调用,但捆绑包没有我设置的键/值onSaveInstanceState(Bundle)

之后,onRestoreInstanceState(Bundle)使用具有正确键/值的包调用。

于 2013-10-22T00:04:48.163 回答
0

我刚遇到这个,并注意到文档有我的答案:

“永远不会以空状态调用此函数。”

https://developer.android.com/reference/android/view/View.html#onRestoreInstanceState(android.os.Parcelable)

就我而言,我想知道为什么在初始实例化时没有调用 onRestoreInstanceState 。这也意味着如果你不存储任何东西,当你去重建你的视图时它不会被调用。

于 2016-05-18T01:36:26.297 回答
0

我可以这样做(对不起,它是 c# 而不是 java,但这不是问题......):

private int iValue = 1234567890;

function void MyTest()
{
    Intent oIntent = new Intent (this, typeof(Camera2Activity));
    Bundle oBundle = new Bundle();
    oBundle.PutInt("MYVALUE", iValue); //=> 1234567890
    oIntent.PutExtras (oBundle);
    iRequestCode = 1111;
    StartActivityForResult (oIntent, 1111);
}

并在您的活动中获得结果

private int iValue = 0;

protected override void OnCreate(Bundle bundle)
{
    Bundle oBundle =  Intent.Extras;
    if (oBundle != null)
    {
        iValue = oBundle.GetInt("MYVALUE", 0);
        //=>1234567890
    }
}

private void FinishActivity(bool bResult)
{
    Intent oIntent = new Intent();
    Bundle oBundle = new Bundle();
    oBundle.PutInt("MYVALUE", iValue);//=>1234567890
    oIntent.PutExtras(oBundle);
    if (bResult)
        {
            SetResult (Result.Ok, oIntent);
        }
    else
        SetResult(Result.Canceled, oIntent);
    GC.Collect();
    Finish();
}

最后

protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
    base.OnActivityResult (iRequestCode, oResultCode, oIntent);
    iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}
于 2016-06-29T14:38:54.333 回答