将值传递给捆绑包时出现奇怪的情况

发布于 2024-12-11 04:52:07 字数 1945 浏览 0 评论 0原文

当我的游戏置于后台时,我使用 onSaveInstanceState 和 onRestoreInstanceState 来保存我的关卡数据。一切似乎工作正常,但当您使用电源按钮锁定手机时,我遇到了一个一致的问题。我不只是拨打“保存”电话,同时还接到一个要恢复的电话,然后又接到另一个要保存的电话,然后当我再次解锁手机时,我又接到另一个要保存的电话,最后又接到另一个要恢复的电话。我已经使用日志标签检查了我的值,我的 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 文件。

I am using onSaveInstanceState and onRestoreInstanceState to keep hold of my level data once my game is put in the background. It all seems to work fine but I have come across a consistent problem when you lock the phone using the power button. Instead of just calling save I also get a call to restore at the same time and then another call to save, then when I unlock my phone again I get another call to save and finally another call to restore. I have checked my values using Log tags and the first time my ArrayList gets returned as empty is after the second call to save after I lock my phone. Here is my stack trace:

//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[]

The same thing doesn't occur when I exit the app by other means.

Here are my onSave and OnRestore methods:

 @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));
}

Is there a way to stop this from happening, if not could I have some tips to help me get my code to recognise the missing data and re-read the CSV file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

差↓一点笑了 2024-12-18 04:52:07

在这篇文章(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() 后,您的 Activity 被终止,然后再次创建,因为您错过了恢复 中的状态onCreate() 你的ArrayList是空的。

一般来说,onRestoreInstanceState() 用于特殊情况,即某些奇特/奇怪的 UI 需要非标准恢复其状态。

In this post (http://ogrelab.ikratko.com/activity-lifecycle-explained-in-details/) there is a sample project which demostrates via logcat lifecycle events and when and which method is called. Long story short: you need to restore your state in onCreate(), not in onRestoreInstanceState().

Here is a sample of the log , when phone is locked:

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

As you can see, after invoking onSaveInstanceState() your activity is killed, then created again and because you miss to recover your state in onCreate() your ArrayList is empty.

Generally speaking onRestoreInstanceState() is used in special cases when some fancy / strange UI needs non-standard recovery of its state.

握住你手 2024-12-18 04:52:07

这有点盲目,但第二次保存可能无法找到数据,因为它在恢复后调用得太快。我猜想这些方法在同一个线程上运行,但我会尝试同步数据对象以查看它是否实际上是竞争条件。

@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));
    }
}

This is kind of a shot in the dark, but the second save may be failing to find the data because it's been called too quickly after restore. I would have guessed that these methods were running on the same thread, but I'd try synchronizing on the data object to see if it's actually a race condition.

@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));
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文