Сохраняются ли фрагменты с setRetainInstance (true) при остановке процесса?

Учитывая этот сценарий: если я создал действие, и он перемещается в фоновый режим, и это действие содержит Fragment, который установлен в setRetainInstance(true), тогда ОС Android может в какой-то момент все же решить закрыть процесс хостинга активности чтобы освободить память.

Затем состояние Activity сохраняется через onSaveInstanceState(Bundle), где - насколько я понял - связанный Bundle записывается, а в файловую систему - выходить из процесса. (таким образом, требование объектов в расслоении Serializable). Позже состояние приложений можно получить в новом процессе через onRestoreInstanceState(Bundle).

Напротив, my Fragment разрешено содержать переменные, которые не обязательно Serializable. Поэтому, я полагал, Fragment не может быть сохранен на диске, например, Bundle. Итак, что происходит с моим фрагментом, когда процесс убивается?

Мне было интересно узнать это руководство разработчика (http://developer.android.com/guide/components/processes-and-threads.html):

Процесс, содержащий активность, которая в настоящее время не видна пользователю (был вызван метод onStop()). Эти процессы не оказывает прямого воздействия на пользовательский опыт, а система может их убить в любое время, чтобы вернуть память для переднего плана, видимого или служебного обработать. Обычно выполняется много фоновых процессов, поэтому они хранятся в LRU (наименее недавно использованный) список, чтобы гарантировать, что процесс, который недавно был замечен пользователем, последний должен быть убит. Если действие реализует его методы жизненного цикла правильно и сохраняет текущее состояние, а его процесс не будет оказывают заметное влияние на пользовательский интерфейс, поскольку, когда пользователь возвращается к активности, действие восстанавливает все его видимое состояние.

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

Означает ли это предположение?

Ответ 1

Похоже, вы смешиваете две концепции здесь.

  • Сохранение состояния в Configuration Configuration не предполагает сериализации. Если вы запросите setRetainInstance() для Fragment, значит, он полностью останется в памяти и не будет воссоздан только для изменений конфигурации. Подобный механизм доступен для объектов Activity, но им необходимо явно определить Object, который будет сохранен. Это работает через Activity.onRetainNonConfigurationInstance(), а не через onSaveInstanceStae().
  • Другой механизм включает в себя сериализацию и возможно (возможно, не всегда, не уверен) ввода/вывода файловой системы, чтобы иметь возможность воспроизводить информацию о состоянии, даже если уничтожен Activity/Fragment (что происходит независимо от его хостинга Process, кстати). Это работает через Activity.onSaveInstanceState() и Fragment.onSaveInstanceState().
  • Конечно, вы можете использовать второй механизм для первого, тем самым замедляя то, как ваше приложение имеет дело с изменениями конфигурации. В зависимости от вашего внутреннего состояния замедление может меня незначительно повлиять.

Относительно ваших вопросов.

  • "Мой фрагмент, напротив, позволяет содержать переменные, которые не могут быть сериализованы". Ну, то же самое верно и для вашего Activity. Он может содержать несериализуемые объекты, которые могут быть сохранены в конфигурационных изменениях, как описано выше.
  • "фрагмент не может быть сохранен на диск при завершении процесса и должен быть воссоздан при восстановлении активности". Нет, оба механизма доступны для обоих типов объектов.

Надеюсь, я мог бы внести свой вклад в это немного разъяснить.

Изменить после вашего первого комментария.

Относительно комментария:

  • "onRetainNonConfigurationInstance устарел": Да. Я упомянул об этом в демонстрационных целях из-за конкретной формулировки в вашем вопросе. Кроме того, с устройствами Android 2, имеющими долю рынка на 46% в соответствии с сегодняшним днем ​​(официальные данные Google), этот метод определенно останется в течение очень долгого времени, устарел или нет.
  • "Моя основная забота о том, что произойдет с экземпляром фрагмента, когда мой хостинг-процесс будет убит и удален из памяти": экземпляр вашего фрагмента будет удален из памяти, и, конечно, нет способа восстановить его с помощью его полное внутреннее состояние автоматически. Это делается только тогда, когда вы setRetainInstanceState в случае изменений конфигурации. (Но обратите внимание, что это относится к экземпляру, другими словами, к полному объекту.)

Относительно вашего редактирования:

  • Еще раз да, ваш Fragment Bundle будет сохранен и восстановлен в/из Bundle независимо от setRetainInstanceState, если вы используете Fragment.onSaveInstanceState() для этой цели, для всего, что имеет смысл.
  • Неверно, что "все его видимое состояние" будет сохранено как текст, на который вы ссылаетесь; например, атрибут visibility не будет сохранен. Будь то ошибка или функция, которую я не знаю, но это факт. Но это только побочное замечание; Элементы пользовательского интерфейса сохраняют большую часть своего соответствующего состояния.
  • "состояние процесса записывается в файловую систему": Нет! Состояние объектов, которые могут сохранить свое состояние в Bundle и фактически реализовать сохранение своего состояния, будет сохранено в Bundle, это означает, что вы должны предоставить такую ​​информацию самостоятельно, если хотите, чтобы ваш Fragment сохранил некоторые информацию о состоянии. Кроме того, опять же: Нет, это связано не только с убийством процесса, но и с удалением объектов Activity и Fragment, которые не видны; как показано в последней активности - Process может остаться в живых.
  • "читаются для возобновления процесса": Нет, Bundle будет прочитан, чтобы передать его на перестройку объектов Activity и/или Fragment, в этом процессе ничего не делается автоматически (кроме объектов библиотеки которые сохраняют свое состояние, также восстанавливают свое состояние), но Android не "возобновляет" "процесс" из этих Bundle s.
  • "Поскольку сохранение фрагментов не связано с методами жизненного цикла": Опять же, я думаю, вы смешиваете эти два понятия. "Сохранение" Fragment выполняется только после изменений конфигурации _IF_, которые вы запрашиваете через setRetainInstance, но мы в основном говорим о воссоздании объектов Fragment из Bundle здесь, что связано с методы жизненного цикла, описанные Google.
  • "Я не знаю, как сохранить, например, указатель на сетевое соединение": опять же, это должно быть утверждение, основанное на вашем путанице. Конечно, вы можете сохранить ссылку на сетевое подключение при изменении конфигурации (по запросу за setRetainInstance), потому что, когда это происходит, все просто хранится в памяти. Кроме того, даже если ваш Fragment будет удален (потому что он стал невидимым), и ваш процесс все еще существует (поскольку он показывает следующее действие), вы можете (и должны) хранить ссылки на объекты, которые дорого воссоздавать, например как сетевое соединение, в вашем объекте Application, который существует до тех пор, пока ваш процесс живет (более или менее). Только когда все ваше приложение убито Android, вы теряете все, но сериализацию, которую мы обсуждаем, происходит гораздо чаще.

Ваше заключение:

Я пришел к выводу, что их обязательно нужно воссоздать, и поэтому методы жизненного цикла, по возможности, предпочтительнее, чем setRetainInstance (true). Имеет ли это предположение какой-либо смысл?

К сожалению, нет, поскольку вы смешиваете совершенно независимые понятия.

Я дам ему последнюю попытку:

  • Вам нужно сохранить ссылку на сетевое подключение, которая вам нужна во всем приложении, в вашем объекте Application, потому что это будет отвратительный пользовательский интерфейс, если вы создадите его с нуля на регулярной основе в своем приложении.
  • Ваш объект Application будет только умирать, если Android убьет ваше приложение.
  • Объекты Activity и Fragment будут удалены из вашего приложения регулярно, когда пользователь перемещается вперед в вашем приложении.
  • Когда пользователь нажимает "назад", Android будет повторно создавать объекты Activity и Fragment из Bundle с использованием методов жизненного цикла. Сохранение чего-то в Bundle имеет смысл, если у вас есть дорогостоящие вычисления для повторного создания внутреннего состояния. Вы можете жить без механизма Bundle, потому что Android всегда будет сохранять Intent, поэтому, если вы ничего не сделаете, вы начнете без сохраненного состояния.
  • При изменении конфигурации Android позволяет оптимизировать работу пользователя, сохраняя объекты в памяти при изменении конфигурации. Здесь используются методы жизненного цикла Activity, и это зависит от вашей реализации, чтобы эффективно использовать сохраненные данные. Для Fragment s это означает, что setRetainInstance' comes into play: Your Fragment` выживет при изменении конфигурации в памяти, если вы установите его.