Странный случай при передаче значений в пакет - PullRequest
1 голос
/ 23 октября 2011

Я использую 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.

Ответы [ 2 ]

1 голос
/ 23 октября 2011

В этом посте (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() используется в особых случаях, когда какой-то необычный / странный пользовательский интерфейс требует нестандартного восстановления своего состояния.

1 голос
/ 23 октября 2011

Это своего рода выстрел в темноте, но при втором сохранении может не получиться найти данные, поскольку они были вызваны слишком быстро после восстановления.Я бы предположил, что эти методы выполняются в одном и том же потоке, но я бы попробовал синхронизироваться с объектом данных, чтобы увидеть, действительно ли это условие гонки.

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