savedInstanceState始终为空
这是我的savedInstaceState代码:
@Override public void onSaveInstanceState(Bundle savedInstanceState) { savedInstanceState.putStringArrayList("todo_arraylist", Altodo); Log.v("bundle", "Saved"); super.onSaveInstanceState(savedInstanceState); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { Altodo = savedInstanceState.getStringArrayList("todo_arraylist"); Log.v("bundle", "Restored"); } else { Log.v("bundle", "null"); } setContentView(R.layout.main); }
日志始终显示“捆绑保存”标签。
但是在onCreate
方法中, SavedInstanceState
始终为空。
我在具有两个扩展了ActionBarActivity
活动A和B的项目中观察到完全相同的症状(报告为问题133394 )。 活动A是主要活动,当从详细视图活动B返回时,我总是在其列表片段的onCreate
中为savedInstanceState
接收null
。 几个小时后,这个问题就变成了一个伪装的导航问题。
以下内容可能与我的设置有关,来自本页的其他答案:
- 鉴于这个答案,我确保片段和活动每个都有唯一的ID集。
- 没有
super
调用,不会覆盖onSaveInstanceState
。 - Activity A在
AndroidManifest.xml
被指定为acitivy B的父级,同时使用android:parentActivityName
属性和早期版本的Android的相应meta-data
标签(请参阅“ 提供导航 ”)。
已经没有任何相应的创build代码,如getActionBar()
.setHomeButtonEnabled(true)
,活动B在其操作栏中有一个运行后退button( < )。 当点击这个button时,活动A重新出现,但是(a)所有以前的实例状态丢失, (b)总是调用onCreate
, (c) savedInstanceState
总是为null
。
有趣的是,当我点击提供在仿真器显示底部边缘的后退button(一个打开的三angular形指向左侧)时,活动A就会像剩下的一样重新出现(即其实例状态完全保留),而不会调用onCreate
。 所以导航可能有问题吗?
在阅读更多内容之后 ,我实现了自己的导航指令,以响应活动B中的后退button:
@Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) NavUtils.navigateUpFromSameTask(this); return true; } return super.onOptionsItemSelected(item); }
与恢复活动A的实例状态相关的任何内容都没有变化。 NavUtils
还提供了一个方法getParentActivityIntent(Activity)
和navigateUpTo(Activity, Intent)
,通过设置FLAG_ACTIVITY_CLEAR_TOP
标志,允许我们修改导航意图,明确指示活动A不是新鲜的(因此没有提供保存的实例状态)
如果已设置,并且正在启动的活动已在当前任务中运行,则不会启动该活动的新实例,而是closures其上的所有其他活动,并将此Intent交付给(现在开启顶端)旧活动作为一个新的意图。
在我的手中,这解决了实例状态丢失的问题,可能看起来像:
public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId()== android.R.id.home) { Intent intent = NavUtils.getParentActivityIntent(this); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); NavUtils.navigateUpTo(this, intent); return true; } return super.onOptionsItemSelected(item); }
请注意,在其他情况下,用户可以从不同的任务中直接切换到活动B (见这里 ),这可能不是完整的解决scheme。 另外,不使用NavUtils
行为可能相同的解决scheme是简单地调用finish()
:
public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId()== android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); }
这两个解决scheme都在我的手中。 我只是猜测原始问题是后退button的稍微不正确的默认实现,它可能与调用某种错过FLAG_ACTIVITY_CLEAR_TOP
的navigateUp
实现有关。
你有没有检查,如果你有一个Id设置为该视图(如果它是/有…)。 否则,不会调用onSaveInstanceState()。
检查这个链接 。
以这种方式保存的状态不会持续下去。 如果整个应用程序在debugging过程中被杀死,那么bundle在onCreate
中将始终为空。
这个IMO是另一个糟糕的Android文档的例子。 这也是为什么市场上的大多数应用程序都没有正确保存状态的原因。
在清单中添加这一行的活动
android:launchMode="singleTop"
例如:
<activity android:name=".ActivityUniversity" android:label="@string/university" android:launchMode="singleTop" android:parentActivityName="com.alkhorazmiy.dtm.ActivityChart"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.alkhorazmiy.dtm.ActivityChart" /> </activity>
不应该super.onSaveInstanceState(savedInstanceState);
成为你的重写的第一行?
编辑 :War_Hero在评论中指出, 关于该主题的文档指出不,它不应该是第一行。
你如何testing它?
Imo最好的testing方法是使用“设置”>“开发人员选项”中的“不要保留活动”标志。 如果您在“设置”中没有“开发者选项”,请参阅启用设备上的开发者选项 。
- 打开你的活动
- 长按回家
- 转到另一个应用程序
- 长按回家
- 回到你的应用程序
在AndroidManifest.xml
检查您的活动,如果为true,则删除android:noHistory
属性。
<activity // .... android:noHistory="false" />
要进行debugging,请考虑实现onRestoreInstanceState并在此方法中调用Log.d。 然后,在模拟器中,按Ctrl-F11或任何旋转手机。 你打给Log.d的电话应该打。
实现onRestoreInstanceState
方法,并在其中放置下面的代码
Altodo = savedInstanceState.getStringArrayList("todo_arraylist");
我发现,当我重写onSaveInstanceState()
并实际保存一些数据在Bundle
,实例状态恢复。 否则它不是。