Жизненный цикл фрагмента

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

Для управления жизненным циклом Fragment реализует LifecycleOwner, предоставляя объект Lifecycle, к которому можно получить доступ с помощью метода getLifecycle().

Каждое возможное состояние Lifecycle представлено в перечислении Lifecycle.State.

Создавая Fragment на основе Lifecycle, вы можете использовать методы и классы, доступные для управления жизненными циклами с помощью компонентов, учитывающих жизненный цикл. Например, вы можете показывать местоположение устройства на экране, используя компонент, учитывающий жизненный цикл. Этот компонент может автоматически начинать прослушивание, когда фрагмент становится активным, и останавливать его, когда фрагмент переходит в неактивное состояние.

В качестве альтернативы использованию LifecycleObserver класс Fragment включает методы обратного вызова, которые соответствуют каждому из изменений в жизненном цикле фрагмента. К ним относятся: onCreate(), onStart(), onResume(), onPause(), onStop() и onDestroy().

У представления фрагмента есть отдельный Lifecycle, который управляется независимо от Lifecycle фрагмента. Фрагменты поддерживают LifecycleOwner для своего представления, доступ к которому можно получить с помощью getViewLifecycleOwner() или getViewLifecycleOwnerLiveData(). Доступ к Lifecycle представления полезен в ситуациях, когда компонент, учитывающий жизненный цикл, должен выполнять работу только во время существования представления фрагмента, например наблюдать за LiveData, который должен отображаться только на экране.

В этой статье подробно рассматривается жизненный цикл Fragment, объясняются некоторые правила, определяющие состояние жизненного цикла фрагмента, и показывается связь между состояниями Lifecycle и обратными вызовами жизненного цикла фрагмента.

Фрагменты и менеджер фрагментов

При создании экземпляра фрагмента он переходит в состояние INITIALIZED. Чтобы фрагмент мог пройти через остальные этапы своего жизненного цикла, его необходимо добавить в FragmentManager. FragmentManager определяет, в каком состоянии должен находиться фрагмент, и переводит его в это состояние.

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

Обратный вызов onAttach() выполняется, когда фрагмент добавлен в FragmentManager и прикреплен к объекту activity. В этот момент фрагмент активен, а FragmentManager управляет состоянием его жизненного цикла. В этот момент методы FragmentManager, такие как findFragmentById(), возвращают этот фрагмент.

Метод onAttach() всегда вызывается до изменения статуса жизненного цикла.

Обратный вызов метода onDetach() происходит, когда фрагмент удален из FragmentManager и отсоединен от своего хоста. Фрагмент больше не активен и не может быть получен с помощью findFragmentById().

onDetach() всегда вызывается после изменения статуса жизненного цикла.

Обратите внимание, что эти обратные вызовы не связаны с методами FragmentTransaction attach() и detach(). Подробнее о транзакциях для работы с фрагментами…

Состояния жизненного цикла фрагмента и обратные вызовы

При определении состояния жизненного цикла фрагмента FragmentManager учитывает следующее:

  • Максимальное состояние фрагмента определяется его FragmentManager. Фрагмент не может перейти в состояние, которое не достигнуто его FragmentManager.
  • В рамках FragmentTransaction вы можете задать максимальное состояние жизненного цикла для фрагмента с помощью setMaxLifecycle() .
  • Состояние жизненного цикла фрагмента не может быть выше, чем у его родительского элемента. Например, родительский фрагмент или действие должны быть запущены до дочерних фрагментов. Аналогично, дочерние фрагменты должны быть остановлены до родительского фрагмента или действия.
состояния жизненного цикла фрагмента и их связь с обратными вызовами жизненного цикла фрагмента и жизненным циклом представления фрагмента;
Рисунок 1. Состояния фрагмента Lifecycle и их связь с обратными вызовами жизненного цикла фрагмента и областью просмотра фрагмента Lifecycle.

На рисунке 1 показаны все состояния Lifecycle фрагмента и их связь с обратными вызовами жизненного цикла фрагмента и представлением Lifecycle фрагмента.

По мере прохождения жизненного цикла фрагмент перемещается вверх и вниз по своим состояниям. Например, фрагмент, который добавляется в верхнюю часть обратного стека, перемещается вверх от CREATED к STARTED и RESUMED. И наоборот, когда фрагмент извлекается из обратного стека, он проходит через эти состояния в обратном порядке: от RESUMED к STARTED, затем к CREATED и, наконец, к DESTROYED.

Переходы в более высокий статус

При переходе к более поздним состояниям жизненного цикла фрагмент сначала вызывает связанный обратный вызов жизненного цикла для своего нового состояния. После завершения этого обратного вызова соответствующий Lifecycle.Event передается наблюдателям через Lifecycle фрагмента, а затем через Lifecycle представления фрагмента, если оно было создано.

Фрагмент создан

Когда фрагмент достигает состояния CREATED, он добавляется в FragmentManager и вызывается метод onAttach().

Здесь можно восстановить сохраненное состояние, связанное с самим фрагментом, через его метод SavedStateRegistry. Обратите внимание, что представление фрагмента в этот момент не создано и любое состояние, связанное с представлением фрагмента, должно быть восстановлено только после создания представления.

Этот переход вызывает обратный вызов onCreate(). Обратный вызов также получает аргумент savedInstanceState Bundle, содержащий любое состояние, ранее сохраненное методом onSaveInstanceState(). Обратите внимание, что при первом создании фрагмента savedInstanceState имеет значение null, но при последующих воссозданиях оно всегда отлично от null, даже если вы не переопределяете onSaveInstanceState(). Подробнее о том, как сохранять состояние с помощью фрагментов…

Фрагмент создан, представление инициализировано

Представление фрагмента Lifecycle создается, только если Fragment предоставляет действительный экземпляр View. В большинстве случаев можно использовать конструкторы фрагментов, которые принимают @LayoutId и автоматически заполняют представление в нужное время. Вы также можете переопределить метод onCreateView(), чтобы программно создать представление фрагмента.

Если и только если представление фрагмента создано с ненулевым значением View, это значение View задается для фрагмента и может быть получено с помощью getView(). Затем getViewLifecycleOwnerLiveData() обновляется с помощью нового INITIALIZED LifecycleOwner, соответствующего представлению фрагмента. В этот момент также вызывается обратный вызов жизненного цикла onViewCreated().

Здесь можно задать начальное состояние представления, начать отслеживать экземпляры LiveData, обратные вызовы которых обновляют представление фрагмента, и настроить адаптеры для экземпляров RecyclerView или ViewPager2 в представлении фрагмента.

Фрагмент и представление созданы

После создания представления фрагмента восстанавливается предыдущее состояние представления, если оно есть, а затем Lifecycle представления переводится в состояние CREATED. Владелец жизненного цикла представления также отправляет наблюдателям событие ON_CREATE. Здесь вы должны восстановить любое дополнительное состояние, связанное с представлением фрагмента.

При этом также вызывается обратный вызов onViewStateRestored().

Фрагмент и представление: НАЧАТО

Настоятельно рекомендуется привязывать компоненты, учитывающие жизненный цикл, к состоянию STARTED фрагмента. Это гарантирует, что представление фрагмента доступно (если оно было создано) и что можно безопасно выполнить FragmentTransaction для дочернего элемента FragmentManager фрагмента. Если представление фрагмента не равно null, то представление фрагмента Lifecycle перемещается в STARTED сразу после того, как Lifecycle фрагмента перемещается в STARTED.

Когда фрагмент переходит в состояние STARTED, вызывается обратный вызов onStart().

Фрагмент и представление RESUMED

Когда фрагмент становится видимым, все эффекты Animator и Transition завершаются, и фрагмент готов к взаимодействию с пользователем. Lifecycle фрагмента переходит в состояние RESUMED, и вызывается обратный вызов onResume().

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

Переход в состояние с более низким приоритетом

Когда фрагмент переходит в более низкое состояние жизненного цикла, соответствующее событие Lifecycle.Event передается наблюдателям сначала представлением Lifecycle фрагмента (если оно создано), а затем самим фрагментом Lifecycle. После того как событие жизненного цикла фрагмента создано, фрагмент вызывает связанный обратный вызов жизненного цикла.

Фрагмент и представление STARTED

Когда пользователь начинает покидать фрагмент, пока он ещё виден, объекты Lifecycle для фрагмента и его представления возвращаются в состояние STARTED и отправляют наблюдателям событие ON_PAUSE. Затем фрагмент вызывает обратный вызов onPause().

Фрагмент и представление созданы

Когда фрагмент перестает быть видимым, Lifecycle для фрагмента и его представления переходят в состояние CREATED и отправляют наблюдателям событие ON_STOP. Этот переход состояния запускается не только при остановке родительского объекта activity или фрагмента, но и при сохранении состояния родительским объектом activity или фрагментом. Это гарантирует, что событие ON_STOP будет вызвано до сохранения состояния фрагмента. Таким образом, событие ON_STOP – это последний момент, когда можно безопасно выполнить FragmentTransaction для дочернего элемента FragmentManager.

Как показано на рисунке 2, порядок обратного вызова onStop() и сохранения состояния с помощью onSaveInstanceState() зависит от уровня API. Для всех уровней API до 28 метод onSaveInstanceState() вызывается до onStop(). Для уровня API 28 и выше порядок вызова обратный.

различия в порядке вызова onStop() и onSaveInstanceState()
Рисунок 2. Различия в порядке вызова для onStop() и onSaveInstanceState().

Фрагмент создан, а представление удалено

После завершения всех анимаций и переходов и отсоединения представления фрагмента от окна представление фрагмента Lifecycle переходит в состояние DESTROYED и отправляет наблюдателям событие ON_DESTROY. Затем фрагмент вызывает обратный вызов onDestroyView(). В этот момент представление фрагмента достигает конца своего жизненного цикла, а метод getViewLifecycleOwnerLiveData() возвращает значение null.

На этом этапе все ссылки на представление фрагмента должны быть удалены, чтобы представление фрагмента могло быть удалено сборщиком мусора.

Фрагмент уничтожен

Если фрагмент удален или FragmentManager уничтожен, Lifecycle фрагмента переходит в состояние DESTROYED и отправляет событие ON_DESTROY своим наблюдателям. Затем фрагмент вызывает обратный вызов onDestroy(). На этом этапе фрагмент достиг конца своего жизненного цикла.

Дополнительные ресурсы

Дополнительную информацию о жизненном цикле фрагментов можно найти в следующих ресурсах.

Руководства

Блоги