Страницы

Поиск по вопросам

среда, 1 января 2020 г.

объект Bundle равен null в onCreate()

#java #android #activity #activity_life_cycle #onsaveinstancestate


Я сохраняю состояние активити в onSaveInstanceState().

Если открыть список недавних приложений и закрыть моё, а потом запустить, в onCreate()
передается null; а если не закрывать, а просто открыть другое приложение, а потом вернуться,
onCreate() не вызовется.
onRestoreInstanceState() не вызывается никогда.

UPD
Как сохранить данные при закрытии приложения, чтобы когда пользователь откроет его
потом, он увидел старое состояние активити?
    


Ответы

Ответ 1



Должно быть вы новичок в Android, но все мы с чего-то начинаем. Вам не хватает знаний о жизненном цикле активности. Подробнее можете прочитать здесь: http://developer.alexanderklimov.ru/android/theory/lifecycle.php Касательно ваших вопросов: метод protected void onCreate(Bundle savedInstanceState) вызывается при создании активности. Активность создается когда мы впервые её открываем или же когда меняем ориентацию с вертикальной на горизонтальную и наоборот. В первом случае savedInstance = null, потому что в нём нет информации и появиться неоткуда. Второй вариант интереснее. При повороте устройства старая активность уничтожается, но перед своим исчезновением успевает вызвать protected void onSaveInstanceState(Bundle outState). Значение outState передается в качестве аргумента в новую активность в метод onCreate(Bundle savedInstanceState). Если вы явно не укажете какие параметры нужно передать в новую активность, то Bundle savedInstanceState будет равен null. Разберём настоящее приложение. Для этого нам поможет инструмент LogCat. В методах onCreate, onSavedInstance, и onDestroy выведем в LogCat информацию, что именно этот метод был вызван. Пр-р: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("myTag", "call onCreate()"); if (savedInstanceState == null){ Log.i("myTag", "saveInstanceState == null"); } else { Log.i("myTag", "saveInstanceState != null"); } } @Override protected void onDestroy() { Log.i("myTag", "call onDestroy"); super.onDestroy(); } @Override protected void onSaveInstanceState(Bundle outState) { Log.i("myTag", "call onSaveInstanceState"); outState.putString("i", "j"); super.onSaveInstanceState(outState); } Пояснения к картинке Строка 1. Мы заходим в приложение и тем самым запускаем главную активность. В этот момент запускается метод onCreate(Bundle savedInstanceState). Строка 2. В методе onCreate(Bundle savedInstanceState) мы сравниваем Bundle savedInstanceState с null. Соответствующую запись выводим в LogCat. Строка 3. Мы меняем ориентацию экрана устройства. (переворачиваем из вертикального положения в горизонтальное или наоборот). Вызывается метод onSaveInstanceState(Bundle outState). Для того, чтобы Bundle outState не был пустым я предварительно в методе onSaveInstanceState(Bundle outState) добавил строку outState.putString("keyForString", "The string I want to save.");. Строка 4. Активность уничтожается, вызывая метод onDestroy(); Строка 5. Создается новая активность, вызывается метод onCreate(Bundle savedInstanceState). Строка 6. В методе onCreate(Bundle savedInstanceState) мы сравниваем Bundle savedInstanceState с null. Но в методе onSaveInstanceState(Bundle outState) мы добавили свою строку, которая находится в объекте Bundle savedInstanceState. Поэтому мы видим что savedInstanceState != null. Строка 7. Я удовлетворился результатом и нажал кнопку назад. Т.о. мы закрыли текущую активность и видим, что вызвался метод onDestroy(). Идём дальше а если не закрывать, а просто открыть другое приложение, а потом вернуться, onCreate() не вызовется. Верно, метод onCreateне вызовется, вместо него вызовется метод onStart. По ранее указанной ссылке вы наглядно увидите, что после того как вы скрыли приложение вызовется метод onStop, а при возвращении вызовется onStart. Пример из документации: https://developer.android.com/training/basics/activity-lifecycle/recreating.html?hl=ru#SaveState Сохранение состояния операции Когда начинается остановка операции, система вызывает метод onSaveInstanceState(), чтобы операция могла сохранить информацию о состоянии с помощью набора пар "ключ-значение". По умолчанию при реализации этого метода сохраняется информация о состоянии иерархии представления операции, например текст в виджете EditText или положение экрана для ListView. Для сохранения дополнительной информации о состоянии операции необходимо реализовать onSaveInstanceState() и добавить к объекту Bundle пары "ключ-значение". Например: static final String STATE_SCORE = "playerScore"; static final String STATE_LEVEL = "playerLevel"; ... @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save the user's current game state savedInstanceState.putInt(STATE_SCORE, mCurrentScore); savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel); // Always call the superclass so it can save the view hierarchy state super.onSaveInstanceState(savedInstanceState); } Внимание! Реализацию суперкласса onSaveInstanceState() следует вызывать во всех случаях, чтобы реализация по умолчанию могла сохранить состояние новой иерархии. Восстановление состояния операции В случае воссоздания операции после предыдущего уничтожения сохраненное состояние можно восстановить из Bundle, куда система передает данные операции. Методы обратного вызова onCreate() и onRestoreInstanceState() получают один и тот же Bundle, содержащий информацию о состоянии экземпляра. Поскольку метод onCreate() вызывается, если система создает новый экземпляр операции или восстанавливает предыдущий экземпляр, перед попыткой чтения необходимо убедиться, что Bundle имеет состояние null. В этом случае система создает новый экземпляр операции вместо восстановления ранее уничтоженного экземпляра. Приведем пример восстановления некоторых данных о состоянии в onCreate(): @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance if (savedInstanceState != null) { // Restore value of members from saved state mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance } ... } Вместо восстановления состояния в onCreate() вы можете реализовать метод onRestoreInstanceState(), который система вызывает после метода onStart(). Система вызывает onRestoreInstanceState() только при наличии сохраненного состояния для восстановления, и поэтому вам не нужно проверять, имеет ли Bundle значение null: public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy super.onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance mCurrentScore = savedInstanceState.getInt(STATE_SCORE); mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); } Внимание! Реализацию суперкласса onRestoreInstanceState() следует вызывать во всех случаях, чтобы реализация по умолчанию могла сохранить состояние новой иерархии.

Комментариев нет:

Отправить комментарий