我正在使用onSaveInstanceState和onRestoreInstanceState来保持我的等级数据,一旦我的游戏放在后台。这一切似乎都运行正常,但是当您使用电源按钮锁定手机时,我遇到了一致的问题。而不只是调用保存我也同时接到一个恢复呼叫然后另一个保存呼叫,然后当我再次解锁我的手机时,我得到另一个保存呼叫,最后另一个呼叫恢复。我已经使用Log标签检查了我的值,并且第一次将我的ArrayList返回为空时是在我锁定手机后第二次调用保存之后。这是我的堆栈跟踪:
//Locks Phone
10-23 08:34:03.797: DEBUG/input(6535): saveLevel[001, 001, 001, 001, 001, 001, 001, 000, 000, 000, 000, 001, 000, 001, 001, 001, 001, 000, 000, 000, 000, 000, 000, 000, 001, 001, 001, 001, 001, 001, 000, 000, 000, 001, 000, 001, 001, 001, 001, 001, 001, 001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000]
10-23 08:34:04.813: DEBUG/input(6535): RestoredLevel[001, 001, 001, 001, 001, 001, 001, 000, 000, 000, 000, 001, 000, 001, 001, 001, 001, 000, 000, 000, 000, 000, 000, 000, 001, 001, 001, 001, 001, 001, 000, 000, 000, 001, 000, 001, 001, 001, 001, 001, 001, 001, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000]
10-23 08:34:05.602: DEBUG/input(6535): saveLevel[]
//Unlocks Phone
10-23 08:34:14.656: DEBUG/input(6535): saveLevel[]
10-23 08:34:14.836: DEBUG/input(6535): RestoredLevel[]
当我通过其他方式退出应用程序时,不会发生同样的事情。
以下是我的onSave和OnRestore方法:
@Override
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
levelDat = CSVReader.getleveldat(); //CSVReader is the class that creates the ArrayList
outState.putStringArrayList("LEVELDATA", levelDat);
Log.d(TAG, "saveLevel" + String.valueOf(levelDat));
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
levelDat = savedInstanceState.getStringArrayList("LEVELDATA");
MRenderer.recoverLevel(); // just a method to force update my level data in my renderer.
Log.d(TAG, "RestoredLevel" + String.valueOf(levelDat));
}
有没有办法阻止这种情况发生,如果没有,我可以提供一些技巧来帮助我让我的代码识别丢失的数据并重新读取CSV文件。
答案 0 :(得分:1)
这是一个黑暗中的镜头,但第二次保存可能无法找到数据,因为它在恢复后被调用得太快。我猜想这些方法在同一个线程上运行,但我会尝试在数据对象上进行同步,看看它是否真的是竞争条件。
@Override
protected void onSaveInstanceState(Bundle outState) {
synchronized(levelDat) {
super.onSaveInstanceState(outState);
levelDat = CSVReader.getleveldat(); //CSVReader is the class that creates the ArrayList
outState.putStringArrayList("LEVELDATA", levelDat);
Log.d(TAG, "saveLevel" + String.valueOf(levelDat));
}
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
synchonized(levelDat) {
super.onRestoreInstanceState(savedInstanceState);
levelDat = savedInstanceState.getStringArrayList("LEVELDATA");
MRenderer.recoverLevel(); // just a method to force update my level data in my renderer.
Log.d(TAG, "RestoredLevel" + String.valueOf(levelDat));
}
}
答案 1 :(得分:1)
在这篇文章中(http://ogrelab.ikratko.com/activity-lifecycle-explained-in-details/),有一个示例项目,它通过logcat生命周期事件以及何时调用哪个方法进行演示。简而言之:您需要在onCreate()
中恢复您的州,而不是onRestoreInstanceState()
。
以下是手机锁定时的日志示例:
10-23 10:50:20.847: I/TEST(913): A onSaveInstanceState
10-23 10:50:20.847: I/TEST(913): A onPause
10-23 10:50:20.847: I/TEST(913): A onStop
10-23 10:50:20.847: I/TEST(913): A onDestroy | isFinishing: false
10-23 10:50:20.859: I/TEST(913): A onCreate
10-23 10:50:20.859: I/TEST(913): A onStart
10-23 10:50:20.859: I/TEST(913): A onRestoreInstanceState
10-23 10:50:20.863: I/TEST(913): A onResume
10-23 10:50:21.210: I/TEST(913): A onSaveInstanceState
10-23 10:50:21.210: I/TEST(913): A onPause
正如您所看到的,在调用onSaveInstanceState()
后,您的活动被终止,然后再次创建,因为您错过了在onCreate()
中恢复状态,您的ArrayList为空。
一般来说,onRestoreInstanceState()
用于特殊情况,当某些花哨/奇怪的UI需要非标准的状态恢复时。