Savedinstancestate android что это
Полный список
— сохраняем данные при повороте экрана
Теорию по этому вопросу можно почитать тут. Я здесь вкратце дам вольный перевод.
Эти методы используются в случаях, когда 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.
Повернем эмулятор обратно в вертикальную ориентацию. Запустим приложение, и жмем на кнопку 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 для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Настройки и состояние приложения
Сохранение состояния приложения
Чтобы точнее понять проблему, с которой мы можем столкнуться, рассмотрим пример. Изменим файл activity_main следующим образом:
Здесь определено поле EditText, в которое вводим имя. И также определена кнопка для его сохранения.
Теперь изменим класс MainActivity :
Запустим приложение введем какое-нибудь имя, сохраним и получим его в TextView:
Но если мы перейдем к альбомному режиму, то TextView окажется пустым, несмотря на то, что в него вроде бы уже получили нужное значение:
И даже если мы попробуем заново получить значение из переменной name, то мы увидим, что она обнулилась:
Чтобы избежать подобных ситуаций как раз и следует сохранять и восстанавливать состояние activity. Для этого изменим код MainActivity:
put() : универсальный метод, который добавляет значение типа Object. Соответственно поле получения данное значение необходимо преобразовать к нужному типу
putString() : добавляет объект типа String
putInt() : добавляет значение типа int
putByte() : добавляет значение типа byte
putChar() : добавляет значение типа char
putShort() : добавляет значение типа short
putLong() : добавляет значение типа long
putFloat() : добавляет значение типа float
putDouble() : добавляет значение типа double
putBoolean() : добавляет значение типа boolean
putCharArray() : добавляет массив объектов char
putIntArray() : добавляет массив объектов int
putFloatArray() : добавляет массив объектов float
putSerializable() : добавляет объект интерфейса Serializable
putParcelable() : добавляет объект Parcelable
get() : универсальный метод, который возвращает значение типа Object. Соответственно поле получения данное значение необходимо преобразовать к нужному типу
getString() : возвращает объект типа String
getInt() : возвращает значение типа int
getByte() : возвращает значение типа byte
getChar() : возвращает значение типа char
getShort() : возвращает значение типа short
getLong() : возвращает значение типа long
getFloat() : возвращает значение типа float
getDouble() : возвращает значение типа double
getBoolean() : возвращает значение типа boolean
getCharArray() : возвращает массив объектов char
getIntArray() : возвращает массив объектов int
getFloatArray() : возвращает массив объектов float
getSerializable() : возвращает объект интерфейса Serializable
getParcelable() : возвращает объект Parcelable
Для примера рассмотрим сохранение-получение более сложных данных. Например, объектов определенного класса. Пусть у нас есть класс User :
Пусть у нас будет следующий интерфейс в activity_main.xml :
Здесь определены два поля ввода для имени и возраста соответственно.
В классе MainActivity пропишем логику сохранения и получения данных:
Здесь также сохраняем данные в переменную User, которая предварительно инициализированна некоторыми данными по умолчанию. А при нажатии на кнопку получения получем данные из переменной и передаем их для вывода в текстовое поле.
Методы активности
Методы
В статье приведены только часть методов. Остальные изучайте самостоятельно через документацию.
При переходе активности от одного состояния к другому, она получает уведомления через защищенные методы:
Из перечисленных методов в вашем классе обязательно должен быть метод onCreate(), которая задаёт начальную установку параметров при инициализации активности. Вторым по популярности является метод onPause(), используемый для сохранения пользовательских настроек активности и подготовиться к прекращению взаимодействия с пользователем.
При реализации любого из этих методов необходимо всегда сначала вызывать версию этого метода из суперкласса. Например:
Семь перечисленных методов определяют весь жизненный цикл активности. Есть три вложенных цикла, которые вы можете отслеживать в классе активности:
Можно написать код с заглушками для методов внутри Активности, которые обрабатывают изменения состояний. Комментарии к каждой такой заглушке описывают действия, которые нужно учитывать при обработке этих событий.
Как видно из кода, переопределяя эти обработчики, вы всегда должны вызывать одноимённые методы родительского класса.
Методы жизненного цикла описаны в отдельной статье. Здесь их опишем кратко и рассмотрим другие методы.
Метод addContentView()
Метод addContentView() добавляет компонент к уже существующей разметке. Пример смотрите здесь.
Метод findViewById()
Метод findViewById() позволяет получить ссылку на View, которая размещена в разметке через его идентификатор.
Если вы используете фрагменты, то когда они загружаются в активность, то компоненты, входящие в состав фрагмента, становятся частью иерархии активности. И вы можете использовать метод findViewById() для получения ссылки к компоненту фрагмента.
Не путать с одноимённым методом для класса View.
Метод finish()
C помощью метода finish() можно завершить работу активности. Если приложение состоит из одной активности, то этого делать не следует, так как система сама завершит работу приложения. Если же приложение содержит несколько активностей, между которыми нужно переключаться, то данный метод позволяет экономить ресурсы.
Метод getFragmentManager()
Каждая активность включает в себя Менеджер фрагментов для управления фрагментами, если они используются. Метод getFragmentManager() позволяет получить доступ к данному менеджеру. На сайте есть отдельные статьи, посвящённые фрагментам.
Метод getParentActivityIntent()
Возвращает намерение, которое может запускать активность, являющей родительской. Родительская активность прописывается в манифесте. Вы можете переопределить данное намерение для своих целей. Метод появился в API 16.
Метод onActivityResult()
Дочерняя активность может произвольно возвратить назад объект Intent, содержащий любые дополнительные данные. Вся эта информация в родительской активности появляется через метод обратного вызова Activity.onActivityResult(), наряду с идентификатором, который она первоначально предоставила.
Если дочерняя активность завершится неудачно или будет закрыта пользователем без подтверждения ввода через кнопку Back, то родительская активность получит результат с кодом RESULT_CANCELED.
Метод принимает несколько параметров:
Метод onBackPressed()
Метод, позволяющий отследить нажатине на кнопку Back. Появился в Android 2.0 (API 5). Пример использования можно посмотреть в статье Кнопка Back: Вы уверены, что хотите выйти из программы?.
Метод onConfigurationChanged()
Метод, который вызывается при изменении конфигурации устройства. Если в манифесте были установлены специальные параметры у атрибута android:configChanges, то данный метод не будет вызван.
Метод onKeyShortcut()
Метод onPostCreate()
Новый метод, который появился в API 21. Он вызывается позже onCreate() и в нём можно получить значения размеров компонентов, которые недоступны при построении интерфейса в методе onCreate().
Метод overridePendingTransition()
Метод overridePendingTransition() позволяет задать анимацию при переходе от одной активности к другой. Пример смотрите здесь.
Метод onRestoreInstanceState()
У метода onRestoreInstanceState() есть такой же параметр Bundle, как у onCreate(), и вы можете восстанавливать сохранённые значения из метода onSaveInstanceState(). Во многих случаях это пример личных предпочтений, какой из двух методов использовать для восстановления данных.
Метод вызывается после метода onStart(). Система вызывает метод onRestoreInstanceState() только в том случае, если имеются сохранённые данные для восстановления. Таким образом вам не нужно проверять Bundle на null, как в методе onCreate():
Метод onSaveInstanceState()
Когда система завершает активность в принудительном порядке, чтобы освободить ресурсы для других приложений, пользователь может снова вызвать эту активность с сохранённым предыдущим состоянием. Чтобы зафиксировать состояние активности перед её уничтожением, в классе активности необходимо реализовать метод onSaveinstancestate().
Сам метод вызывается прямо перед методом onPause(). Он предоставляет возможность сохранять состояние пользовательского интерфейса активности в объект Bundle, который потом будет передаваться в методы onCreate() и onRestoreInstanceState(). В объект Bundle можно записать параметры, динамическое состояние активности как пары «ключ-значение». Когда активность будет снова вызвана, объект Bundle передаётся системой в качестве параметра в методы onCreate() и onRestoreInstanceState(), которые вызываются после onStart(), чтобы один из них или они оба могли установить активность в предыдущее состояние. Прежде чем передавать изменённый параметр Bundle в обработчик родительского класса, сохраните значения с помощью методов putXXX() и восстановите с помощью getXXX().
Используйте обработчик onSaveInstanceState() для сохранения состояния интерфейса (например, состояния флажков, текущего выделенного элемента или введенных, но не сохранённых данных), чтобы объект Activity при следующем входе в активное состояние мог вывести на экран тот же UI. Рассчитывайте, что перед завершением работы процесса во время активного состояния будут вызваны обработчики onSaveInstanceState и onPause.
В отличие от базовых методов, методы onSaveInstanceState() и onRestoreInstanceState() не относятся к методам жизненного цикла активности. Система будет вызывать их не во всех случаях. Например, Android вызывает onSaveinstancestate() прежде, чем активность становится уязвимой к уничтожению системой, но не вызывает его, когда экземпляр активности разрушается пользовательским действием (при нажатии клавиши BACK). В этом случае нет никаких причин для сохранения состояния активности.
Метод onSaveInstanceState() вызывается системой в случае изменения конфигурации устройства в процессе выполнения приложения (например, при вращении устройства пользователем или выдвижении физической клавиатуры устройства.
Поскольку метод onSaveinstanceState() вызывается не во всех случаях, его необходимо использовать только для сохранения промежуточного состояния активности. Для сохранения данных лучше использовать метод onPause().
Этот обработчик будет срабатывать всякий раз, когда жизненный цикл активности начнёт подходить к концу, но только в том случае, если её работа не будет завершена явно (при вызове метода finish()). Вследствие этого обработчик используется для проверки целостности состояния активности между активными жизненными циклами одиночной пользовательской сессии.
Сохранённый параметр Bundle передается методам onRestoreInstanceState() и onCreate(), если приложение принудительно перезапускается на протяжении сессии. В листинге показано, как извлечь значения из этого параметра и использовать их для обновления состояния экземпляра активности.
В API 28 метод вызывается после метода onStop(), в ранних версиях до метода onStop().
Метод onUserLeaveHint()
Позволяет отследить нажатие кнопки Home
Метод requestWindowFeature()
Метод позволяет задействовать дополнительные возможности для активности, например, выводить экран активности без заголовка. Примеры смотрите здесь.
Метод onWindowFocusChanged()
Метод позволяет определить момент получения фокуса вашим приложением.
Метод может быть полезен, так как он срабатывает позже метода onCreate(). Например, для вычисления размеров кнопки на экране этот метод предпочтительнее, так как уже известно, что все элементы загрузились и доступны, тогда как в onCreate() могут возвратиться пустые значения ширины и высоты кнопки. Пример использования.
Метод setContentView()
Изначально экран активности пуст. Чтобы разместить пользовательский интерфейс, необходимо вызвать метод setContentView(). У метода есть две перегруженные версии. Вы можете передать в параметре либо экземпляр компонента (View), либо идентификатор ресурса (наиболее распространённый способ).
Пример с использованием экземпляра компонента:
В этом примере вы увидите на экране текстовое поле с текстом. Но при таком способе вы можете использовать только один компонент. А если экран состоит из множества кнопок и прочих элементов управления, то нужно использовать разметку.
Метод setFeatureDrawableResource()
С помощью данного метода можно вывести значки в правой части заголовка. Смотри пример.
Метод setRequestedOrientation()
Метод позволяет программно изменить ориентацию экрана. Пример использования.
Метод startActivity()
Чтобы запустить новую активность, используется метод startActivity(Intent). Этот метод принимает единственный параметр — объект Intent, описывающий активность, которая будет запускаться. Смотри пример Activity.
Метод startActivityForResult()
Иногда требуется вернуть результат активности, когда она закрывается. Например, можно запустить активность, которая позволяет пользователю выбирать человека в списке контактов. При закрытии активность возвращает данные человека, который был выбран: его полное имя и телефон. В этом случае необходимо вызвать метод startActivityForResult()
Метод startActivityForResult(Intent, int) со вторым параметром, идентифицирующим запрос позволяет возвращать результат. Когда дочерняя активность закрывается, то в родительской активности срабатывает метод onActivityResult(int, int, Intent), который содержит возвращённый результат, определённый в родительской активности.
Метод setResult()
Когда активность завершится, вы можете вызвать метод setResult(int), чтобы возвратить данные назад в родительскую активность (до метода finish()). Этот метод возвращает код результата закрытия активности, который может быть стандартными результатами Activity.RESULT_CANCELED, Activity.RESULT_OK или определяемым пользователем результатом RESULT_FiRST_USER (можете придумать любую константу с целочисленным значением).
Если в дочерней активности есть кнопка отмены, то код может быть следующим:
Если метод finish() вызвать раньше метода setResult(), то результирующий код установится в RESULT_CANCELED автоматически, а возвращённое намерение покажет значение null.
Сохранение состояния активности Android с помощью сохранения состояния экземпляра
Я работал на платформе Android SDK, и немного неясно, как сохранить состояние приложения. Таким образом, учитывая этот незначительный переинструмент примера «Hello, Android»:
Я думал, что этого будет достаточно для самого простого случая, но он всегда отвечает первым сообщением, независимо от того, как я удаляюсь от приложения.
Я уверен, что решение так же просто, как переопределение onPause или что-то в этом роде, но я копался в документации в течение 30 минут или так и не нашли ничего очевидного.
27 ответов
вам нужно переопределить onSaveInstanceState(Bundle savedInstanceState) и напишите значения состояния приложения, которые вы хотите изменить на
на savedInstanceState предназначен только для сохранения состояния, связанного с текущим экземпляром действия, например текущей навигации или информации выбора, так что если Android уничтожает и воссоздает действие, оно может вернуться, как это было раньше. См. документацию для onCreate и onSaveInstanceState
для более длительного состояния рассмотрите возможность использования базы данных SQLite, файла или настроек. См.Сохранение Постоянного Состояния.
обратите внимание, что он является не безопасно использовать onSaveInstanceState и onRestoreInstanceState для постоянных данных, согласно документации по состояниям деятельности в http://developer.android.com/reference/android/app/Activity.html.
в документе говорится (в разделе «жизненный цикл активности»):
обратите внимание, что важно сохранить постоянные данные в onPause() вместо из onSaveInstanceState(Bundle) потому что позже не часть обратные вызовы жизненного цикла, поэтому не будет позвонила в каждой ситуации, как описано в его документации.
редактировать: для дальнейшего уточнения, вот onSaveInstanceState() документы:
мой коллега написал статью, объясняющую состояние приложения на устройствах Android, включая пояснения по жизненному циклу активности и информации о состоянии, как хранить информацию о состоянии и сохранять в состояние Bundle и SharedPreferences и посмотреть здесь.
статья охватывает три подхода:
храните локальные данные Управления varible / UI для срока службы приложения (т. е. временно) с помощью пакета состояний экземпляра
магазин местный varible / UI control data между экземплярами приложений (т. е. постоянно) с использованием общих настроек
сохранение экземпляров объектов в памяти между действиями в течение срока службы приложения с использованием сохраненного экземпляра без конфигурации
Это классический «gotcha» развития Android. Здесь есть два вопроса:
во-первых, чтобы прояснить «предполагаемое» поведение: onSaveInstance и onRestoreInstance являются хрупкими и только для переходного состояния. Предполагаемое использование (afaict) для обработки отдыха активности, когда телефон поворот (изменение ориентации). Другими словами, предполагаемое использование-это когда ваша деятельность все еще логически «сверху», но все еще должна быть восстановлена системой. Сохраненный пакет не сохраняется за пределами process / memory / gc, поэтому вы не можете полагаться на это, если ваша деятельность идет в фоновом режиме. Да, возможно, память вашей деятельности переживет свое путешествие на задний план и избежит GC, но это ненадежно (и не предсказуемо).
Так что если у вас есть сценарий, где существует значимый «прогресс пользователя» или состояние, которое должно сохраняться между «запусками» вашего приложения, руководство по использованию onPause и onResume. Вы должны сами выбрать и подготовить постоянное хранилище.
но-есть очень запутанная ошибка, которая усложняет все это. Детали здесь:
Я боролся с этими потоками в течение нескольких часов, прежде чем понял, что моей главной проблемой была эта ошибка, а не предполагаемое поведение фреймворка. Большое сочинение и решение (обновление: см. ниже), похоже, от пользователя @kaciula в этом ответе:
обновление июнь 2013: месяцы спустя я, наконец, нашел «правильное» решение. Вам не нужно самостоятельно управлять флагами startedapp, вы можете обнаружить это из фреймворка и внести соответствующий залог. Я использую это в начале моей LauncherActivity.метод onCreate:
onSaveInstanceState вызывается, когда система нуждается в памяти и убивает приложение. Это не вызывается, когда пользователь просто закрывает приложение. Поэтому я думаю, что состояние приложения также должно быть сохранено в onPause Он должен быть сохранен в некотором постоянном хранилище, например Preferences или Sqlite
оба метода полезны и действительны, и оба лучше всего подходят для разных сценариев:
Это не тот подход лучше другого, как и все, просто важно понять, какое поведение вам требуется и выбрать наиболее подходящий подход.
сохранение состояния-это kludge в лучшем случае, насколько я обеспокоен. Если вам нужно сохранить постоянные данные, просто использовать SQLite
думаю, я нашел ответ. Позвольте мне рассказать, что я сделал простыми словами:
Предположим, у меня есть два вида деятельности, activity1 и activity2, и я перехожу от activity1 к activity2 (я сделал некоторые работы в activity2) и снова к действию 1, нажав на кнопку в activity1. Теперь на этом этапе я хотел вернуться к activity2, и я хочу видеть свою activity2 в том же состоянии, когда я в последний раз покидал activity2.
для приведенного выше сценария, что я сделал разве что в манифесте я сделал некоторые изменения вроде этого:
и в activity1 на кнопке нажмите событие, которое я сделал так:
и в activity2 на кнопке нажмите событие, которое я сделал так:
Теперь произойдет то, что все изменения, которые мы внесли в activity2, не будут потеряны, и мы сможем просмотреть activity2 в том же состоянии, в котором мы оставили ранее.
Я считаю, что это ответ, и это работает штраф для меня. Поправьте меня, если я ошибаюсь.
воссоздание активности
чтобы сохранить дополнительные данные о состоянии активности, необходимо переопределить метод обратного вызова onSaveInstanceState (). Система вызывает этот метод, когда пользователь покидает вашу активность и передает ему объект Bundle, который будет сохранен в случае, если ваша активность будет неожиданно уничтожена. Если система должна воссоздать экземпляр activity позже, она передает один и тот же объект Bundle обоим onRestoreInstanceState() и onCreate() методы.
когда система начинает останавливать вашу деятельность, она вызывает onSaveInstanceState() (1) таким образом, вы можете указать дополнительные данные состояния, которые вы хотите сохранить, если экземпляр действия должен быть воссоздан. Если деятельность уничтожена и один и тот же экземпляр должен быть воссоздан, система передает данные состояния, определенные в (1), обоим onCreate() Метод (2) и onRestoreInstanceState() метод (3).
Сохранить Activity государство
чтобы сохранить дополнительную информацию о состоянии для вашей деятельности, вы должны реализовать onSaveInstanceState() и добавьте пары ключ-значение в объект Bundle. Например:
внимание: всегда вызывайте реализацию суперкласса onSaveInstanceState() таким образом, реализация по умолчанию может сохранить состояние иерархии представлений.
Восстановить Activity государство
потому что onCreate() метод вызывается независимо от того, создает ли система новый экземпляр вашей активности или воссоздает предыдущий, вы должны проверить, является ли пакет состояния нулевым, прежде чем пытаться его прочитать. Если это null, затем система создает новый экземпляр действия вместо восстановления предыдущего, который был уничтожен.
например, вот как вы можете восстановить некоторые данные состояния в onCreate() :
onSaveInstanceState() для переходных данных (восстановлено в onCreate() / onRestoreInstanceState() ), onPause() для постоянных данных (восстановлен в onResume() ). Из технических ресурсов Android:
данные метода onsaveinstance() вызывается Android, если действие прекращается и может быть убито до его возобновления! Это означает, что он должен хранить любое состояние, необходимое для повторной инициализации в том же состоянии при перезапуске действия. Это аналог метода onCreate (), и на самом деле пакет savedInstanceState переданного в метод onCreate() является одной связке, что вы построить как outState в данные метода onsaveinstance() метод.
onPause () и onResume() также являются бесплатными методами. onPause () всегда вызывается, когда действие заканчивается, даже если мы инициировали это (например, с вызовом finish ()). Мы будем использовать это, чтобы сохранить текущую запись в базе данных. Передовая практика заключается в высвобождении любых ресурсов, которые могут быть высвобождены в методов onPause (), чтобы занимать меньше ресурсов, когда в пассивном состоянии.
действительно onSaveInstance состояние callen, когда действие переходит в background
между тем я вообще больше не использую
живой цикл для большинства видов деятельности слишком сложен и не нужен. И сам google заявляет, что он даже не надежен.
мой способ-сохранить любые изменения сразу в настройках
в некотором роде SharedPreferences работают аналогично пакетам. И естественно и поначалу такие значения должны быть красными от предпочтений.
в случае сложных данных вы можете использовать SQLite вместо использования предпочтений.
при применении этой концепции действие просто продолжает использовать последнее сохраненное состояние, независимо от того, было ли это начальное открытие с перезагрузками между ними или повторное открытие из-за заднего стека.
чтобы уменьшить шаблон, я использую следующее interface и class читать/писать Bundle для сохранения состояния экземпляра.
сначала создайте интерфейс, который будет использоваться для аннотирования переменных экземпляра:
затем создайте класс, в котором отражение будет использоваться для сохранения значений в комплекте:
пример использования:
Примечание: этот код был адаптирован из проект библиотекиAndroidAutowire который лицензирован под лицензия MIT.
чтобы ответить на исходный вопрос напрямую. savedInstancestate имеет значение null, поскольку ваша активность никогда не создается повторно.
ваша деятельность будет воссоздана только с помощью пакета состояний, когда:
Android уничтожит фоновые действия, когда под давлением памяти или после того, как они были в фоновом режиме в течение длительного периода времени.
при тестировании вашего примера hello world есть несколько способов уйти и вернуться к деятельности.
в большинстве случаев, если вы просто нажимаете home, а затем снова запускаете приложение, Активность не нужно будет повторно создавать. Он уже существует в памяти, поэтому onCreate () не будет вызываться.
другие ответы ценны тем, что они учат вас правильным способам хранения состояния, но я не чувствовал, что они действительно ответили, почему ваш код не работает так, как вы ожидали.
на onSaveInstanceState(bundle) и onRestoreInstanceState(bundle) методы полезны для сохранения данных просто при вращении экрана (изменение ориентации).
Они даже не хороши при переключении между приложениями (так как onSaveInstanceState() метод называется but onCreate(bundle) и onRestoreInstanceState(bundle) больше не вызывается.
Для большей сохраняемости используйте общие настройки. прочитать эту статью
моя проблема заключалась в том, что я нуждался в постоянстве только во время жизни приложения (т. е. одно выполнение, включая запуск других под-действий в том же приложении и поворот устройства и т. д.). Я пробовал различные комбинации вышеуказанных ответов, но не получал того, что хотел во всех ситуациях. В конце концов, мне удалось получить ссылку на savedInstanceState во время onCreate:
и использовать это, чтобы получить содержимое моей переменной, когда мне это нужно, по строчкам:
я использую onSaveInstanceState и onRestoreInstanceState как было предложено выше, но я думаю, что я мог бы также или альтернативно использовать мой метод для сохранения переменной при ее изменении (например, используя putBoolean )
хотя принятый ответ правильный, есть более быстрый и простой способ сохранить состояние активности на Android с помощью библиотеки под названием Пешне. Icepick-это процессор аннотаций, который заботится обо всем шаблонном коде, используемом для сохранения и восстановления состояния.
делать что-то подобное с Icepick:
это то же самое, что делать это:
есть в основном два способа реализовать это изменение.
Я действительно не рекомендую использовать второй метод. Поскольку в одном из моих опытов это вызывало половину экрана устройства черным при вращении от портрета к пейзажу и наоборот.
используя первый метод, упомянутый выше, мы можем сохранять данные при изменении ориентации или изменении конфигурации происходит. Я знаю способ, которым вы можете хранить любые данные внутри объекта состояния savedInstance.
теперь в вашей активности в onCreate и методом данные метода onsaveinstance выполните следующие действия. Это будет выглядеть примерно так:
при создании действия вызывается метод onCreate ().
savedInstanceState-это объект класса Bundle, который впервые имеет значение null, но содержит значения при его воссоздании. Чтобы сохранить состояние активности, вы должны переопределить данные метода onsaveinstance().
поместите свои значения в объект пакета «outState», например outState.putString («ключ»,» Добро пожаловать обратно») и сохранить, вызвав super. Когда активность будет уничтожена, это состояние будет сохранено. Объект Bundle и может быть восстановлен после восстановления в onCreate () или onRestoreInstanceState (). Пакет, полученный в onCreate() и onRestoreInstanceState (), одинаковы.
вот, комментарий с Стив Мозлиответ (by ToolmakerSteve), что ставит вещи в перспективу (в целом onSaveInstanceState vs onPause, east cost vs west cost saga)
и затем в onCreate() или onRestoreInstanceState()
добавить значения по умолчанию, если вы не хотите иметь дополнительные возможности
Не уверен, что мое решение неодобрительно или нет, но я использую связанную службу для сохранения состояния ViewModel. Сохраняете ли вы его в памяти службы или сохраняете и извлекаете из базы данных SqlLite, зависит от ваших требований. Это то, что делают службы любого вкуса, они предоставляют такие услуги, как поддержание состояния приложения и абстрактная общая бизнес-логика.
этот подход дает вам дополнительный бонус обеспечения разделения принципа проектирования концерна в том, что все вы приложение бизнес-логика может быть перемещена в службу, которая уменьшает дублированную логику через несколько представлений и позволяет представление для обеспечения соблюдения другого важного принципа проектирования, один Ответственность.
просто быстро решить эту проблему с помощью Пешне
сначала настройте библиотеку в app/build.gradle
теперь, давайте проверим этот пример ниже, Как сохранить состояние активности
он работает для действий, фрагментов или любого объекта, который должен сериализовать свое состояние на связке (например, ViewPresenters миномета)
Icepick также может генерировать код состояния экземпляра для пользовательских представлений:
когда активность уничтожить SaveInstanceState(Bundle savedInstanceState) метод вызывается, и там вы сохраняете данные, которые хотите сохранить. И вы получите то же самое в onCreate() после перезапуска активности.(savedInstanceState не будет null, так как вы сохранили некоторые данные в нем, прежде чем активность будет уничтожена)
теперь Android предоставляет ViewModels для сохранения состояния вы должны попытаться использовать это вместо saveInstanceState.
добавление LiveData (компоненты архитектуры Android) в ваш проект
добавьте следующую зависимость
реализация » android.арка.жизненный цикл:расширения:1.1.0″
LiveData принимает наблюдателя и уведомляет его об изменениях данных только тогда, когда он находится в запущенном или возобновленном состоянии. Преимущество LiveData заключается в том, что когда ваша деятельность переходит в любое состояние, отличное от STARTED или возобновить он не будет называть событий onchanged метод обозреватель.