Android的savedInstanceState始终为空

6
我有以下情况:
  • 活动A启动活动B
  • 活动A调用onPauseonSaveInstanceStateonStop方法。
  • 在活动B上,我按下操作栏上的“向上按钮”
  • 首先销毁活动A(调用onDestroy),然后重新创建。(这似乎只是Android的做法。我没有按照这种方式实现,但似乎是Android的做法..)
  • onCreate方法期间,变量savedInstanceState始终为null。

我知道这里有类似的话题,但没有一个对我的情况有答案。所有回调方法都有日志行,所以我确定保存方法和销毁方法已执行。但为什么从未出现过savedInstanceState对象?

我的保存方法:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putSerializable(OpenSessionsActivity.SESSION, session);
    System.out.println("saving ..");
    super.onSaveInstanceState(savedInstanceState);
}

您还需要我包括其他代码吗?

5个回答

9
顶部活动在向上导航时会重新创建。为了保留活动A的状态,您可以:
A)将活动A的启动模式设置为"singleTop"(在AndroidManifed.xml中添加android:launchMode="singleTop"
或者
B)在从活动B导航时,在up意图中添加FLAG_ACTIVITY_CLEAR_TOP标志。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent up = NavUtils.getParentActivityIntent(this);
            up.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            NavUtils.navigateUpTo(this, up);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

这是一个已记录的行为:

类似地,如果你跳转到当前栈上的一个activity,其行为由父activity的启动模式决定。如果父activity的启动模式为singleTop(或向上导航意图包含FLAG_ACTIVITY_CLEAR_TOP标志),则将父activity带到堆栈顶部,并保留其状态。导航意图由父activity的onNewIntent()方法接收。如果父activity的启动模式为standard(且向上导航意图不包含FLAG_ACTIVITY_CLEAR_TOP标志),则当前activity和其父activity都会从堆栈中弹出,并创建一个新的父activity实例以接收导航意图。


1
这就是我寻找了数小时的答案! - Jamie Cockburn

7

在操作栏上按下向上实际上并不等同于按下返回按钮。

如果您希望它们行为相同,可以在B活动中使用以下代码:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            onBackPressed();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

我对按钮的工作方式感到满意。我只是不想失去活动A的状态。 - Kuurde
我的意思是按上键不会导致Android恢复您的活动。它会创建一个新的活动。尝试一下我发布的代码,看看是否有效。 - Greg Ennis
那么使用内置的UP函数总是会重新创建吗?也许这并不完全符合我的期望..你的代码可行。我现在会使用它,因为它确实省去了我尝试保存活动状态的麻烦。谢谢。 - Kuurde
是的,这相当烦人。我现在几乎一直在使用那段代码。 - Greg Ennis

0
我不得不在清单文件的活动部分中添加android:launchMode="singleTop"才能使它正常工作。然后我只需要

NavUtils.navigateUpFromSameTask(getActivity())


0

你应该放置

super.onSaveInstanceState(savedInstanceState);

在保存自己的数据代码之前。


这会得到相同的结果。 - Kuurde

0

文档中所述:

protected void onSaveInstanceState (Bundle outState):

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

如果您的设备进行方向更改,则会调用 onStop() 和 onSavedInstanceState(...)。


我了解文档。这就是为什么我在那里放置日志行的原因。而且我确信onSavedInstanceState被调用了。如果使用onPause()仍然是更好的解决方案,你能否给出一个示例,说明我如何保存状态?因为没有Bundle对象.. - Kuurde
也许会调用onRestoreInstanceState(Bundle savedInstanceState)方法?如果您有全局状态,可以使用SharedPreferences。 - Nipper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接