Android 将值传递给bundle时出现奇怪的情况

Android 将值传递给bundle时出现奇怪的情况,android,opengl-es,arraylist,save,restore,Android,Opengl Es,Arraylist,Save,Restore,我正在使用onSaveInstanceState和onRestoreInstanceState保存我的关卡数据,一旦我的游戏被放到后台。这一切似乎都很好,但我遇到了一个一贯的问题,当你锁定手机使用电源按钮。除了拨打save,我还同时接到一个要还原的电话,然后又接到另一个要保存的电话,然后当我再次解锁手机时,我接到另一个要保存的电话,最后是另一个要还原的电话。我已经使用日志标记检查了我的值,我的ArrayList第一次返回为空是在我锁定手机后第二次呼叫save之后。这是我的堆栈跟踪: //Lock

我正在使用onSaveInstanceState和onRestoreInstanceState保存我的关卡数据,一旦我的游戏被放到后台。这一切似乎都很好,但我遇到了一个一贯的问题,当你锁定手机使用电源按钮。除了拨打save,我还同时接到一个要还原的电话,然后又接到另一个要保存的电话,然后当我再次解锁手机时,我接到另一个要保存的电话,最后是另一个要还原的电话。我已经使用日志标记检查了我的值,我的ArrayList第一次返回为空是在我锁定手机后第二次呼叫save之后。这是我的堆栈跟踪:

//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文件。

这有点像是瞎猜,但第二次保存可能无法找到数据,因为在还原后调用数据太快。我会猜到这些方法是在同一个线程上运行的,但我会尝试在数据对象上同步,看看它是否真的是一个竞争条件

@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));
    }
}
在这个岗位上(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为空


一般来说,
onrestoreinnstancestate()
用于特殊情况下,当一些奇特的用户界面需要非标准的状态恢复时。

谢谢你的快速回答,但我已经找到了解决办法。我所要做的就是确保CSVReader类中的ArrayList在还原时是最新的(因为渲染器最初从中获取级别数据),并且确保与ArrayList相关的所有变量都已更新(例如:我将ArrayList的大小存储在某个变量中)是否可以只放置
levelDat=savedInstanceState.getStringArrayList(“LEVELDATA”)行从我的还原方法直接进入onCreate?哦,并且在手机锁定后或一段时间后立即调用onDestroy。是的,您可以将
levelDat=…
移动到onCreate()。至少pn我的手机(Galaxy S),
onDestroy()
在锁定后立即被调用。如果我没有实现onDestroy,它不会被调用吗?听起来不太可能。我用的是2.2自动取款机。