onSaveInstanceState()和onRestoreInstanceState()

时间:2010-11-04 11:29:06

标签: android android-activity states

我正在尝试使用方法ActivityonSaveInstanceState()保存并恢复onRestoreInstanceState()的状态。

问题是它永远不会进入onRestoreInstanceState()方法。任何人都可以向我解释为什么会这样吗?

13 个答案:

答案 0 :(得分:186)

通常您会在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");
  }
}

您不必存储视图状态,因为它们通过调用super.onSaveInstanceState(icicle);

自动存储

答案 1 :(得分:147)

只有在操作系统终止后重新创建活动时,

onRestoreInstanceState()才会被称为。这种情况发生在:

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

相反:如果您正在进行活动,并且您点击设备上的Back按钮,则您的活动已完成()编辑(即将其视为退出桌面应用程序),下次启动应用时开始“新鲜”,即没有保存状态,因为当你点击Back时你有意退出它。

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

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

  

大多数实现只会使用onCreate(Bundle)来恢复它们   状态,但有时候在这里做完之后很方便   初始化已完成或允许子类决定是否   使用您的默认实现。这个的默认实现   方法执行以前任何视图状态的恢复   由onSaveInstanceState(Bundle)冻结。

正如我所读到的:没有理由覆盖Activity,除非你是{{1}}的子类,并且预计有人将子类化为子类。

答案 2 :(得分:7)

您在onSaveInstanceState()保存的状态稍后可在onCreate()方法调用中使用。因此,请使用onCreate(及其Bundle参数)来恢复活动状态。

答案 3 :(得分:4)

作为一种变通方法,您可以将包含要维护的数据的包存储在用于启动活动A的Intent中。

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

活动A必须将其传递回活动B.您将在活动B的onCreate方法中检索意图。

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

另一个想法是创建一个存储库类来存储活动状态,并让你的每个活动引用该类(可能使用单例结构。)虽然这样做可能比它的价值更麻烦。

答案 4 :(得分:3)

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

答案 5 :(得分:3)

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

但是,仅当onCreate和onStart也被调用时,才会调用onRestoreInstanceState。并且,onCreate和onStart并不总是被调用。

因此,即使活动移至后台,Android似乎并不总是删除状态信息。但是,为了安全起见,它调用生命周期方法来保存状态。因此,如果状态未被删除,则Android不会调用生命周期方法来恢复状态,因为它们不需要。

Figure 2描述了这一点。

答案 6 :(得分:2)

我认为这个帖子很老了。我只提到另一个案例,即onSaveInstanceState()也将被调用,就是当你致电Activity.moveTaskToBack(boolean nonRootActivity)时。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

onSaveInstanceState之后不一定要调用onRestoreInstanceState。

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

答案 9 :(得分:1)

在文档Restore activity UI state using saved instance state中,其表示为:

您可以选择在onCreate()期间恢复状态,而不是 实现onRestoreInstanceState(),系统会在 onStart()方法。系统仅在以下情况下调用onRestoreInstanceState(): 有一个要保存的状态要恢复,因此您无需检查是否 捆绑商品为空

enter image description here

enter image description here

IMO,与在onCreate上进行检查相比,这是一种更清晰的方法,并且更适合单一职责原则。

答案 10 :(得分:0)

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

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

答案 11 :(得分:0)

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

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

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

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

答案 12 :(得分:0)

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

from nltk.internals import find_jars_within_path
from nltk.parse.stanford import StanfordParser
parser = StanfordParser(model_path="path/to/englishPCFG.ser.gz")
parser._classpath = tuple(find_jars_within_path(stanford_dir))

和你的结果活动

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();

}