Жизненный цикл статического объекта Android

101

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

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

Но я боюсь, если о жизненном цикле статических объектов в Android, если обнаружена низкая память, Android удаляет статические объекты ???

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

d-man
источник

Ответы:

239

Начнем с небольшой предыстории: что происходит, когда вы запускаете приложение?
ОС запускает процесс, назначает ему уникальный идентификатор процесса и выделяет таблицу процессов. Процесс запускает экземпляр DVM (Dalvik VM); Каждое приложение запускается внутри DVM.
DVM управляет выгрузкой загрузки классов, жизненным циклом экземпляра, GC и т. Д.

Время жизни статической переменной: статическая переменная возникает, когда класс загружается JVM, и умирает, когда класс выгружается.

Поэтому, если вы создаете приложение для Android и инициализируете статическую переменную, она останется в JVM до тех пор, пока не произойдет одно из следующих событий:
1. класс не будет выгружен
2. JVM завершит работу
3. процесс завершится

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

Вы можете проверить это с помощью нескольких строк кода:

  1. напечатайте неинициализированную статику в onCreate вашей активности -> должен напечатать null
  2. инициализировать статический. напечатать -> значение будет ненулевым
  3. Нажмите кнопку «Назад» и перейдите на главный экран. Примечание. Главный экран - это еще одно действие.
  4. Запустите свою деятельность снова -> статическая переменная не будет нулевой
  5. Завершите процесс приложения из DDMS (кнопка остановки в окне устройств).
  6. Перезапустите свою деятельность -> статика будет иметь нулевое значение.

Надеюсь, это поможет.

Самух
источник
1
Я хочу знать, почему я теряю значение своего поля в объекте приложения, если оно не является статическим, когда я начинаю новое действие, например, я объявляю переменную текущую страницу в объекте приложения, и его значение всегда возвращается к нулю, когда я открываю новое действие
Мохаммед Субхи Шейх Куруш
когда я вызываю super.onRestoreInstanceState (savedInstanceState); Я теряю свою переменную, даже если они статичны, в чем проблема?
Мохаммед Субхи Шейх Куруш
1
это хорошее объяснение (так что нет -1), но оно немного несущественно: OP явно спросил о «ситуациях с нехваткой памяти» (по той же причине, по которой я здесь), где, насколько я знаю, Os может убить виртуальную машину и перезапустите его позже с теми же параметрами, и этот случай ( ЕСЛИ он реальный) здесь не рассматривается ...
Rick77 07
1
@suitianshi Я думаю, что мы можем инициализировать статические экземпляры в Application.onCreate, потому что даже если наше приложение переходит в фоновый режим и процесс завершается, как только мы вернемся к нашему приложению, класс Application будет создан и вызовет соответствующие методы жизненного цикла очередной раз! хотя мне нужно подтверждение по этому поводу, мне интересно, может ли быть какой-нибудь сценарий, когда статический экземпляр, инициализированный в Application.onCreate, теряет свое значение?
Сартак Миттал
1
Чего мне здесь не хватает, так это объяснения «1. класс выгружен» - когда это произойдет? Будет ли JVM выгружать класс, если ему не хватает памяти?
Stoefln
16

Что ж, шаблон Singleton также основан на использовании статических переменных, поэтому на самом деле вы будете в том же положении. Хотя статический подход может работать в большинстве случаев, может случиться так, что в некоторых случаях, когда память заполнена и другое действие переходит на передний план, прежде чем ваше приложение перейдет к следующему экрану, процесс вашего действия может быть остановлен, и вы потеряете статические значения. Однако Android предлагает несколько вариантов сохранения значений между состояниями или их передачи, например:

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

Вы можете получить несколько примеров кода использования предпочтений, намерений и базы данных sqlite, просмотрев дерево исходного кода aegis-shield в коде Google или в других приложениях Android с открытым исходным кодом.

r1k0
источник
6

После некоторого исследования выясняется, что использование приложения для хранения синглтонов - не такая уж и хорошая идея, если только вы не готовы воссоздать ее:

Не хранить данные в объекте приложения

поэтому, хотя принятый ответ является технически правильным, он не предоставляет всей информации.

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

Rick77
источник
3

@ r1k0 прямо здесь. Хранение данных в статических полях класса не будет сохраняться само по себе при остановках и перезапусках процессов приложения. Android обычно убивает процессы (запущенные приложения), когда ему требуется память.

Согласно документу Android: состояние активности и извлечение из памяти ,

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

Вы можете сохранять и восстанавливать состояние примитивов, а также объектов Serializable и Parcelable, используя следующие методы. Они автоматически вызываются во время нормального жизненного цикла активности.

protected void onSaveInstanceState(Bundle state) {}
protected void onRestoreInstanceState(Bundle savedInstanceState){}

Итак, если у вас есть класс, который имеет только статические переменные, вы можете сохранить состояние каждого поля в onSaveInstanceState () и восстановить их в onRestoreInstanceState (). Когда Android завершает процесс, в котором работает ваше приложение, состояние ваших переменных будет сохранено, а когда Android восстановит ваше приложение, значения будут восстановлены в памяти в том же состоянии, что и раньше.

eric.mcgregor
источник