Почему иногда удается сохранить Hashtable объектов, не предназначенных для Parcelable, в onSaveInstanceState ()? - PullRequest
6 голосов
/ 04 марта 2011

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

Деятельность в приложении сохраняет серию вопросов в Hashtable<Integer, Question>, гдеВопрос - это небольшой класс, содержащий int и две строки.Как изначально написано, упражнение загружает вопросы с сервера на каждый onCreate(), поэтому я хотел внедрить onSaveInstanceState(), чтобы предотвратить некоторые избыточные загрузки.onSaveInstanceState() сохраняет Hashtable в Bundle, используя putSerializable().

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
            // mQuestions is a member variable of 
            // type Hashtable<Integer, Question>
    if (mQuestions != null && mQuestions.size() > 0) {
        outState.putSerializable(SAVED_QUESTIONS, mQuestions);
    }
}

Он отлично работал для изменения ориентации экрана даже до того, как я понял, что такое Parcelable или как его реализовать.Я только знал, что была проблема, когда я нажимал клавишу home на эмуляторе и приложение молча, невидимо зависало без вывода LogCat.Трассировка стека подтолкнула меня к поиску Parcelable и заставила Question реализовать его.

Мой вопрос не в том, что я сделал неправильноВопрос в следующем: Когда класс Question не реализовал Parcelable, почему приложение зависало только при нажатии Home, а не при изменении ориентации экрана?

Ответы [ 3 ]

2 голосов
/ 13 июля 2011

Насколько я понимаю, Android не сериализует состояние экземпляра при воссоздании действия после изменений конфигурации.Вот почему ваш код работает.Сохраняемые объекты просто не должны быть пригодны для разделения, поскольку они существуют только в памяти.

Это похоже на оптимизацию.Android знает, что в этом случае процесс не будет завершен, и нет необходимости сохранять состояние экземпляра в файл.(Теоретически процесс может быть остановлен во время изменения конфигурации, и я не знаю, как Android решает эту проблему).

Но когда пользователь нажимает клавишу Home, ваше приложение становится фоновым.И его процесс может быть прекращен в случае нехватки памяти.Android должен сохранять состояние активности в файл, чтобы иметь возможность восстановить ваше приложение и его действия в будущем.В этом случае состояние экземпляра действительно сериализуется и сохраняется в постоянном хранилище.И именно поэтому ваш код не работает.

Завершение процесса может произойти в любой момент, поэтому вы не можете полагаться на некоторые детали реализации.Просто сделайте состояние экземпляра пригодным для использования или сериализуемым, и вы больше не столкнетесь с этой проблемой.

1 голос
/ 11 июля 2011

Цитирование Стива Мозли

Обратите внимание, что НЕ безопасно использовать onSaveInstanceState и onRestoreInstanceState, согласно документациио состояниях активности в http://developer.android.com/reference/android/app/Activity.html.

В документе говорится (в разделе «Жизненный цикл действия»):

Обратите внимание, что важно сохранять постоянные данные в onPause() вместоonSaveInstanceState(Bundle), поскольку последний не является частью обратных вызовов жизненного цикла, поэтому не будет вызываться в каждой ситуации, как описано в его документации.

Другими словами, введите код сохранения / восстановления в onPause() и onResume() вместо!

0 голосов
/ 14 июля 2011

Приложение не зависало.Он был просто выключен, когда пользователь нажал клавишу Home.Вот почему не было вывода в LogCat.

Установите точку останова в Activity.onDestroy (), чтобы подтвердить это.Если я прав, onDestroy () будет вызываться, но onSaveInstanceState () не будет, потому что onSaveInstanceState () вызывается только тогда, когда приложение находится в фоновом состоянии, а не когда оно закрыто.

Если вам нужночтобы сохранить состояние приложения после завершения работы, поместите код в onDestroy () и сохраните его в нечто более постоянное, чем Bundle.

Barry

...