Android onsaveinstancestate не работает

Как вручную вызвать onSaveInstanceState ()

Я пишу программу, в которой я вызываю несколько макетов для одного и того же действия, но затем я заметил, что когда я переключаю макеты, изменения, сделанные до переключения, не восстанавливаются и onSavedInstanceState(Bundle outState) не вызывается. Я пытался вручную вызвать метод, но не могу получить пакет outState .

Таким образом, вопрос на самом деле заключается в следующем: как мне получить и сохранить текущее состояние действия, которое будет вызвано и / или восстановлено во время моего выбора?

А потом из отдельного класса

2 ответа

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

Также вы не должны использовать setContentView для переключения между представлениями, это дорогой способ сделать это. Возможно, вы захотите проверить ViewSwitcher или ViewFlipper или как-то реализовать фрагменты.

Может быть, вам стоит взглянуть на основы приложения

Android вызывает onSaveInstanceState () до того, как действие становится уязвимым для уничтожения системой, но не беспокоится о том, чтобы вызывать его, когда экземпляр фактически уничтожается действием пользователя (например, нажатием клавиши BACK)

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

Источник

Полный список

— сохраняем данные при повороте экрана

Теорию по этому вопросу можно почитать тут. Я здесь вкратце дам вольный перевод.

Когда работа Activity приостанавливается(onPause или onStop), она остается в памяти и хранит все свои объекты и их значения. И при возврате в Activity, все остается, как было. Но если приостановленное Activity уничтожается, например, при нехватке памяти, то соответственно удаляются и все его объекты. И если к нему снова вернуться, то системе надо заново его создавать и восстанавливать данные, которые были утеряны при уничтожении. Для этих целей Activity предоставляет нам для реализации пару методов: первый позволяет сохранить данные – onSaveInstanceState, а второй – восстановить — onRestoreInstanceState.

Эти методы используются в случаях, когда Activity уничтожается, но есть вероятность, что оно еще будет востребовано в своем текущем состоянии. Т.е. при нехватке памяти или при повороте экрана. Если же вы просто нажали кнопку Back (назад) и тем самым явно сами закрыли Activity, то эти методы не будут выполнены.

Но даже если не реализовать эти методы, у них есть реализация по умолчанию, которая сохранит и восстановит данные в экранных компонентах. Это выполняется для всех экранных компонентов, у которых есть ID.

Создадим простое приложение, чтобы протестить все эти тезисы. Посмотрим, в какой момент вызываются эти методы, попробуем в них что-нить сохранить. Также убедимся, что необходимо вызывать соответствующие методы супер-класса, чтобы сохранялись данные экранных компонентов.

Т.к. нам надо будет поворачивать экран, используйте при разработке Android 2.2. В AVD с версией 2.3 поворот глючит.

Читайте также:  Андроид для телевизора своими руками

Project name: P0701_SaveInstanceState
Build Target: Android 2.2
Application name: SaveInstanceState
Package name: ru.startandroid.develop.p0701saveinstancestate
Create Activity: MainActivity

В strings.xml пропишем тексты:

В main.xml нарисуем кнопку и пару полей для ввода текста:

Обратите внимание, что второй EditText без ID.

В MainActivity будем вызывать все методы Lifecycle и два вышеописанных:

В каждом из них пишем лог, чтобы отследить последовательность вызовов. Метод onclick пока не реализуем.

Все сохраним и запустим. Введем в текстовые поля какие-нить данные:

и повернем экран CTRL+F12.

Данные в первом поле сохранились при повороте, а во втором пропали. Это произошло потому, что дефолтовые методы сохранения/восстановления умеют работать только с компонентами, которые имеют ID. Посмотрим лог.

Эти три метода выполнились при запуске.

Затем мы повернули экран:

onSaveInstanceState
onPause
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onResume

Первым делом вызывается onSaveInstanceState, здесь нам надо будет реализовывать сохранение своих данных. Далее идет уничтожение Activity (onPause, onStop, onDestroy) и создание нового onCreate, onStart. И перед onResume вызывается метод восстановления данных – onRestoreInstanceState.

Последовательность мы рассмотрели — сохраняются данные перед onPause, а восстанавливаются перед onResume. Попробуем теперь что-нибудь сохранить и восстановить. У нас на экране есть кнопка, будем по ее нажатию увеличивать счетчик нажатий на единицу и выводить всплывающее сообщение с итоговым кол-вом нажатий. Переменная cnt у нас уже есть. Реализуем onclick:

Повернем эмулятор обратно в вертикальную ориентацию. Запустим приложение, и жмем на кнопку Count. Видим сообщение с кол-вом нажатий. Нажмем еще несколько раз, получим, например 5.

Теперь повернем экран и снова нажмем кнопку.

Мы видим, что счетчик сбросился.

Это произошло потому, что текущий объект Activity был уничтожен и потерял значения всех переменных, в том числе и cnt. При создании нового Activity значение cnt равно 0 и отсчет пошел заново. Давайте это пофиксим. Реализуем метод сохранения onSaveInstanceState:

В объект outState мы пишем значение переменной cnt. Механизм аналогичен помещению данных в Intent.

Метод восстановления onRestoreInstanceState:

Из savedInstanceState вытаскиваем значение и помещаем в переменную cnt. Теперь при уничтожении и воссоздании Activity переменная cnt сохранит свое значение, и наш счетчик продолжит работать.

Проверим. Вернем AVD в вертикальную ориентацию. Все сохраним, запустим приложение. Понажимаем на кнопку, немного накрутим счетчик

и поворачиваем экран.

Жмем снова кнопку

счетчик не сбросился, а продолжил увеличиваться с последней позиции.

Итак, методы onSaveInstanceState и onRestoreInstanceState по дефолту сохраняют данные в экранных компонентах. Если мы реализуем их самостоятельно, то вызываем методы супер-класса и пишем свой код для своих переменных. Ради интереса, можете попробовать убрать вызовы методов суперкласса из onSaveInstanceState и onRestoreInstanceState. Данные в текстовом поле перестанут сохраняться при повороте экрана.

Кроме метода onRestoreInstanceState, доступ к сохраненным данным также можно получить в методе onCreate. На вход ему подается тот же самый Bundle. Если восстанавливать ничего не нужно, он будет = null.

Есть еще один полезный механизм сохранения данных. Android дает нам возможность сохранить ссылку на какой-либо объект и вернуть ее в новый созданный Activity. Для этого существуют методы:

Читайте также:  Все текстовые редакторы для андроид

onRetainNonConfigurationInstance – в нем мы сохраняем ссылку, передавая ее на выход (return) метода

Т.е., например, у нас есть какой то объект myObj (класс MyObject) и нам надо сохранить ссылку на него при повороте экрана.

Мы реализуем в Activity метод onRetainNonConfigurationInstance:

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

А, при создании нового Activity, в onCreate (например) мы используем метод getLastNonConfigurationInstance:

Мы получили обратно объект класса Object и привели его к нашему классу MyObject.

На следующем уроке:

— используем Preferences для работы с настройками приложения

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Android: onSaveInstanceState не вызывается из активности

У меня есть Activity A, который вызывает Activity B. В Activity B, когда я нажимаю кнопку, вызывается функция finish (), которая в свою очередь вызывает onDestroy () Activity B и возвращается к активности A.

Согласно документации по android, до вызова onDestroy, будет вызываться onSaveInstanceState (Bundle bundle), где я делаю следующее.

И в следующий раз, когда действие B начинается с действия A,

В oncreate (), я делаю следующее:

Однако перед вызовом onDestroy в Activity B метод onSaveInstanceState никогда не вызывается. Любая помощь в этом будет принята с благодарностью.

EDIT: если это невозможно. Пожалуйста, дайте мне знать, есть ли способ сохранить состояние веб-просмотра

Обратите внимание, что onRestoreInstanceState() вызывается, когда активность воссоздана, но только если:

Он был убит ОС . «Такая ситуация возникает, когда:

  • Ориентация устройства изменяется (ваша деятельность уничтожается и воссоздается)
  • Есть еще одна активность перед вами, и в какой-то момент ОС убивает вашу активность, чтобы освободить память (например). В следующий раз, когда вы начнете свою деятельность onRestoreInstanceState() . «

Поэтому, если вы находитесь в своей деятельности, и вы нажимаете кнопку «Назад» на устройстве, ваша деятельность finish() ed, и в следующий раз, когда вы запустите приложение, оно снова запускается (похоже, что оно было заново создано, не так ли?), Но это Без сохранения состояния, потому что вы намеренно покинули его, когда вы нажимаете кнопку «Назад».

У меня была аналогичная ситуация. Это явно ошибка разработчиков. Я переопределил неправильный метод:

Вместо этого правильный :

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

Документация метода onSaveInstanceState говорит:

Не путайте этот метод с обратными вызовами жизненного цикла активности, такими как onPause() , который всегда вызывается, когда действие помещается в фоновом режиме или на его пути к уничтожению, или onStop() который вызывается перед уничтожением. Один пример того, когда onPause() и onStop() а не этот метод, когда пользователь переходит от операции B к активности A: нет необходимости вызывать onSaveInstanceState(Bundle) на B, потому что этот конкретный экземпляр никогда не будет восстановлен , Поэтому система избегает его вызова. Пример, когда onPause() вызывается, а не onSaveInstanceState(Bundle) – это когда активность B запускается перед активностью A: система может не вызывать onSaveInstanceState(Bundle) для активности A, если она не была убита в течение жизни B, поскольку Состояние пользовательского интерфейса A останется неизменным.

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

Читайте также:  Окна или android смартфон

В конце концов вам придется записывать назад / историю в постоянное хранилище. В случае отключения устройства в качестве одного из примеров, а также избегая придуманного (на мой взгляд) примера, в котором вы вызываете onSaveInstanceState в onPause (что вам нужно сделать, чтобы получить пакет, который вы хотите передать в onRestoreInstanceState который вы Затем может перейти в restoreState ).

Поэтому, помимо пересмотра вашего дизайна (если пользователь закрыл ваше приложение и вы не создаете браузер, действительно ли он хочет сохранить ту же историю?), Вы должны посмотреть SharedPreferences и как их использовать.

К сожалению, вы не можете поместить пакет в общие настройки, и я не рекомендую пытаться написать пакет через Parcelable (он предназначен только для IPC, а не для постоянного хранения). Но вы можете сохранить все примитивы, которые хранится в комплекте. Это тоже может быть надуманно, но мне кажется единственным способом получить постоянное хранилище.

А затем перестройте свой пакет через примитивы, хранящиеся в SharedPreferences, и передайте это в restoreState() . Вы можете проверить исходный код Android, чтобы узнать, что на webView.saveState() деле делает webView.saveState() (я искал код 2.1 и, похоже, писал int, сериализуемый объект, а затем еще один пакет для SSL-сертификата. Всего четыре целых числа). В верхней части моей головы я просто напишу все примитивы, которые вы можете, а затем сохраните местоположение (строку) локального файла, который вы также запишете сериализованными данными.

Даже если у вас есть упорядоченная коллекция всего списка BackForward, я не уверен, как перевести это в goBack() и goForward() используя эти значения (есть защищенный метод, который участвует в добавлении элементов в список, но вы можете ‘T доступ к этому). ЕСЛИ вы используете restoreState() , поэтому мы перейдем ко всей работе, чтобы правильно перестроить пакет.

Серьезно, хотя, если мои навыки поиска не являются абсурдными (полностью возможными), сохраняя историю WebView в местах, где saveInstanceState/restoreInstanceState может выполнять вашу работу за вас, похоже, не проблема, с которой сталкиваются многие люди. Т.е. не многие люди пытаются сохранить историю WebView, когда пользователь явно закрывает свое приложение, поэтому вы должны спросить себя, почему вы это делаете?

Извините, если есть действительно простой способ настойчиво хранить эту информацию и перезагружать в WebView btw!

Источник

Оцените статью