Понимание фрагмента setRetainInstance (boolean)

Начиная с документации:

public void setRetainInstance (boolean сохранить)

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

  • onDestroy() не будет вызываться (но onDetach() все равно будет, потому что фрагмент отсоединяется от его текущей активности).
  • onCreate (Bundle) не будет вызываться, так как фрагмент не создается повторно.
  • onAttach (Activity) и onActivityCreated (Bundle) все равно будут вызываться.

У меня есть несколько вопросов:

  • Сохраняет ли фрагмент его представление, или это будет воссоздано при изменении конфигурации? Что именно "сохраняется"?

  • Будет ли уничтожен фрагмент, когда пользователь покинет активность?

  • Почему он не работает с фрагментами в стеке?

  • Каковы варианты использования, когда имеет смысл использовать этот метод?

Ответ 1

Прежде всего, проверьте мой пост на сохраненных фрагментах. Это может помочь.

Теперь, чтобы ответить на ваши вопросы:

Сохраняет ли фрагмент состояние view, или это будет воссоздано при изменении конфигурации - что именно "сохраняется"?

Да, состояние Fragment сохраняется при изменении конфигурации. В частности, "сохраненный" означает, что фрагмент не будет уничтожен при изменениях конфигурации. То есть, Fragment будет сохранен, даже если изменение конфигурации приведет к уничтожению базового Activity.

Будет ли уничтожен фрагмент, когда пользователь покинет действие?

Так же, как Activity s, Fragment может быть уничтожен системой, когда ресурсы памяти низки. Независимо от того, сохранили ли вы свои фрагменты состояние своего экземпляра во всех конфигурационных изменениях, не повлияет ли система на уничтожение Fragment после того, как вы оставите Activity. Если вы оставите Activity (т.е. Нажав кнопку "домой" ), Fragment может быть или не быть уничтожен. Если вы оставите Activity, нажав кнопку "Назад" (таким образом, вызывая finish() и эффективно уничтожая Activity), все Activity прикрепленные Fragment также будут уничтожены.

Почему он не работает с фрагментами в фоновом стеке?

Вероятно, есть несколько причин, почему это не поддерживается, но для меня наиболее очевидной причиной является то, что Activity содержит ссылку на FragmentManager, а FragmentManager управляет стоп-кадром. То есть независимо от того, хотите ли вы сохранить свой Fragment или нет, Activity (и, следовательно, FragmentManager) будет уничтожен при изменении конфигурации. Другая причина, по которой это может не сработать, состоит в том, что вещи могут оказаться сложными, если обе оставшиеся фрагменты и не сохранившиеся фрагменты были разрешены к существованию на одной и той же стороне.

Каковы варианты использования, когда имеет смысл использовать этот метод?

Сохраненные фрагменты могут быть весьма полезны для распространения информации о состоянии - особенно управления потоками - через экземпляры активности. Например, фрагмент может служить хостом для экземпляра Thread или AsyncTask, управляя его работой. Для получения дополнительной информации см. мой пост в блоге.

В общем, я бы рассматривал его так же, как с помощью onConfigurationChanged с Activity... не использовать его как бандад только потому, что вам слишком ленив, чтобы правильно реализовать/изменить ориентацию. Используйте его только тогда, когда вам нужно.

Ответ 2

setRetaininstance полезен только тогда, когда ваш activity уничтожается и воссоздается из-за изменения конфигурации, поскольку экземпляры сохраняются во время вызова onRetainNonConfigurationInstance. То есть, если вы поворачиваете устройство, оставшиеся фрагменты останутся там (они не будут уничтожены и воссозданы.), Но когда среда выполнения убивает активность для восстановления ресурсов, ничего не остается. Когда вы нажмете кнопку "Назад" и выйдите из нее, все будет уничтожено.

Обычно я использую эту функцию для сохранения ориентации, изменяющей Time.Say Я загружаю кучу растровых изображений с сервера, и каждый из них 1 МБ, когда пользователь случайно поворачивает свое устройство, я, конечно, не хочу делать всю работу по загрузке снова. Итак, я создаю Fragment, удерживая мои растровые изображения, добавляя его менеджеру и вызываю setRetaininstance, все растровые изображения все еще существуют, даже если меняется ориентация экрана.

Ответ 3

SetRetainInstance (true) позволяет выживать фрагмент. Его члены будут сохранены при изменении конфигурации, как вращение. Но он все равно может быть убит, когда активность будет убита в фоновом режиме. Если содержащая активность в фоновом режиме была убита системой, она должна быть сохранена системой, которую вы обрабатывали вSaveInstanceState должным образом. Другим словом всегда будет вызываться onSaveInstanceState. Хотя onCreateView не будет вызываться, если SetRetainInstance истинно, а фрагмент/активность еще не убит, он все равно будет вызван, если он будет убит и будет отправлен обратно.

Вот какой анализ активности и фрагмента андроидов надеется, что это поможет. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html

Ответ 4

setRetainInstance(boolean) полезно, если вы хотите иметь какой-то компонент, который не привязан к жизненному циклу активности. Этот метод используется, например, rxloader для "обработки жизненного цикла Android для rxjava Observable" (который я нашел здесь).