Понимание фрагмента setRetainInstance(логическое)
Начиная с документации:
public void setRetainInstance (логическое сохранение)
Управляет сохранением экземпляра фрагмента при повторном создании действия (например, после изменения конфигурации). Это можно использовать только с фрагментами, которые не находятся в заднем стеке. Если установлено, жизненный цикл фрагмента будет немного отличаться при воссоздании действия:
- onDestroy () не будет вызываться (но onDetach() все равно будет, потому что фрагмент отсоединяется от текущей активности).
- onCreate (Bundle) не будет вызываться, так как фрагмент не создается заново.
- onAttach (Activity) и onActivityCreated(Bundle) будут по-прежнему вызываться.
У меня есть несколько вопросов:
Сохраняет ли фрагмент также свой вид, или он будет воссоздан при изменении конфигурации? Что именно "сохраняется"?
Будет ли фрагмент уничтожен, когда пользователь покинет активность?
Почему он не работает с фрагментами на заднем стеке?
В каких случаях целесообразно использовать этот метод?
4 ответа
Прежде всего, проверьте мой пост о сохраненных фрагментах. Это может помочь.
Теперь, чтобы ответить на ваши вопросы:
Сохраняет ли фрагмент также свое состояние
просмотра, или это будет воссоздано при изменении конфигурации - что именно "сохраняется"?
Да, Fragment
Состояние будет сохраняться при изменении конфигурации. В частности, "сохраняется" означает, что фрагмент не будет уничтожен при изменении конфигурации. Это Fragment
будет сохранен, даже если изменение конфигурации вызовет Activity
быть уничтоженным.
Будет ли фрагмент уничтожен, когда пользователь покинет активность?
Как Activity
s, Fragment
Система может быть уничтожена, когда ресурсы памяти невелики. Сохраните ли ваши фрагменты свое состояние экземпляра при изменениях конфигурации, это не повлияет на то, уничтожит ли система Fragment
когда вы покидаете Activity
, Если вы оставите Activity
(то есть нажатием кнопки "Домой"), Fragment
s может быть или не быть уничтожено. Если вы оставите Activity
нажав кнопку назад (таким образом, вызывая finish()
и эффективно уничтожить Activity
), Все Activity
прилагается Fragment
также будут уничтожены.
Почему он не работает с фрагментами на заднем стеке?
Вероятно, есть несколько причин, почему это не поддерживается, но наиболее очевидная причина для меня заключается в том, что Activity
содержит ссылку на FragmentManager
и FragmentManager
управляет backstack. То есть, неважно, если вы решите сохранить свой Fragment
или нет, Activity
(и, таким образом, FragmentManager
backstack) будет уничтожен при изменении конфигурации. Другая причина, по которой это может не сработать, заключается в том, что все может стать сложнее, если разрешить существование как сохраненных фрагментов, так и не сохраненных фрагментов в одном и том же обратном стэке.
В каких случаях целесообразно использовать этот метод?
Сохраненные фрагменты могут быть весьма полезны для распространения информации о состоянии, особенно управления потоками, между экземплярами операций. Например, фрагмент может служить хостом для экземпляра Thread
или же AsyncTask
Управляя своей работой. Смотрите мой блог на эту тему для получения дополнительной информации.
В общем, я бы отнесся к этому аналогично onConfigurationChanged
с Activity
... не используйте его в качестве бандажа только потому, что вы слишком ленивы, чтобы правильно реализовать / обработать изменение ориентации. Используйте его только тогда, когда вам нужно.
setRetaininstance
полезно только когда ваш activity
уничтожается и воссоздается из-за изменения конфигурации, потому что экземпляры сохраняются во время вызова onRetainNonConfigurationInstance
, То есть, если вы поверните устройство, сохраненные фрагменты останутся там (они не будут уничтожены и воссозданы). Но когда среда выполнения убивает действие, чтобы вернуть ресурсы, ничего не остается. Когда вы нажимаете кнопку "Назад" и выходите из игры, все разрушается.
Обычно я использую эту функцию, чтобы сохранить изменение ориентации Time. Скажем, я загрузил несколько растровых изображений с сервера, и каждый из них занимает 1 МБ, когда пользователь случайно поворачивает свое устройство, я, конечно, не хочу снова выполнять всю работу по загрузке. Я создаю Fragment
держа мои растровые изображения и добавить его к менеджеру и позвонить setRetainInstance
все растровые изображения все еще там, даже если ориентация экрана изменяется.
setRetainInstance() - не рекомендуется
В виде фрагментов Версия 1.3.0-alpha01
Метод setRetainInstance() для фрагментов устарел. С введением ViewModels разработчики получили специальный API для сохранения состояния, которое может быть связано с действиями, фрагментами и графами навигации. Это позволяет разработчикам использовать обычный, не сохраняемый фрагмент и сохранять конкретное состояние, которое они хотят сохранить отдельно, избегая общего источника утечек, сохраняя при этом полезные свойства единственного создания и уничтожения сохраненного состояния (а именно, конструктора ViewModel и обратный вызов onCleared(), который он получает).
SetRetainInstance(true) позволяет фрагменту выживать. Его члены будут сохранены во время изменения конфигурации, например, при ротации. Но он все еще может быть убит, когда активность убивается в фоновом режиме. Если содержащая активность в фоновом режиме уничтожена системой, ее instanceState должен быть сохранен системой, которую вы правильно обработали на SaveInstanceState. Другими словами, всегда вызывается onSaveInstanceState. Хотя onCreateView не будет вызываться, если SetRetainInstance имеет значение true, а фрагмент / активность еще не уничтожен, он все равно будет вызываться, если он уничтожен и его пытаются вернуть обратно.
Вот некоторый анализ активности / фрагмента андроида, надеюсь, это поможет. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html
setRetainInstance(boolean) полезен, когда вы хотите иметь какой-то компонент, который не связан с жизненным циклом Activity. Этот метод используется, например, rxloader для "обработки жизненного цикла активности Android для rxjava's Observable" (который я нашел здесь).