Fragment
Fragment
Часть UI, внутри Activity со своим жизненным циклом.
• нельзя создать через конструктор, так как иначе система не восстановит состояние фрагмента, когда это будет нужно.
• получить ссылку на фрагмент из activity: findFragmentByTag
и findFragmentById
.
setRetainInstance
Метод setRetainInstance() принимает boolean параметр. По умолчанию значение retainInstance фрагмента – false. Если retainInstance выставлен в true, то фрагмент переживает пересоздание хост-активити, например при повороте экрана. Когда активити пересоздается, фрагмент с retainInstance=true отсоединяется от старой активити и присоединяется к новой. Поэтому при пересоздании активити у фрагмента не вызываются методы onDestroy
и onCreate
, но вызываются onDetach
onAttach
и onActivityCreated
. setRetainInstance
может быть использован только на фрагментах, не добавленных в backstack.
ActivityStateLossException
Это исключение вида: IllegalStateException: Can not perform this action after onSaveInstanceState with MyFragment. Генерируется, когда метод FragmentTransaction.commit
вызывается после Activity.onSaveInstanceState
. Когда пользователь уходит с активити, состояние сохраняется на случай, если активити будет уничтожена системой. Сохранение состояния происходит в методе onSaveInstanceState
. Если транзакция применяется после сохранения состояния, то транзакция не может быть сохранена и система бросает исключение.
Чем отличается tag
в методах add
и addToBackStack
?
Tag в методе add
присваивается фрагменту. getTag
возвращает этот тег. Тег фрагмента используется в методе findFragmentByTag
. Tag в методе addToBackStack
это на самом деле не tag, а name. Имя транзакции, которое присваивается объекту BackStackEntry и возвращается методом getName
.
Fragment Lifecycle
onAttach | когда фрагмент добавляется в FragmentManager и прикрепляется к Activity . |
onCreate | когда фрагмент создается. Этот метод вызывается после вызова соответствующего метода onCreate у Activity . |
onCreateView | создается иерархия view. В этом методе можно установить, какой именно UI будет использовать фрагмент |
onViewCreated | вызывается после создания представления фрагмента |
onAcyivityCreated | вызывается после того, как отрабатывает метод Activity.onCreate |
onViewStateRestored | вызывается, когда состояние иерархии View восстановлено |
onStart | вызывается, когда фрагмент становится видимым пользователю |
onResume | вызывается, когда фрагмент становится активным для взаимодействия с пользователем |
onPause | фрагмент остается видимым, но с ним уже нельзя взаимодействовать |
onStop | фрагмент становится не видим пользователю |
onDestroyView | метод, в котором фрагмент очищает ресурсы, связанные с иерархией View . |
onDestroy | вызывается перед тем, как фрагмент будет уничтожен системой |
onDetach | вызывается перед тем, как фрагмент будет отсоединен от активити |
FragmentManager
Класс для управления фрагментами. Он позволяет добавлять, удалять, заменять фрагменты, а также управлять их состоянием.
add
Используется для добавления фрагмента в контейнер. При добавлении нового фрагмента через add
, предыдущий фрагмент остается активным, его жизненный цикл не меняется, он продолжает работать в RESUMED
состоянии.
val fragmentManager = supportFragmentManager
val transaction = fragmentManager.beginTransaction()
transaction.add(R.id.fragment_container, MyFragment(), "myFragmentTag")
transaction.commit()
replace
Удаляет текущий фрагмент в контейнере и добавляет новый. Это замещает один фрагмент другим, вызывая полный жизненный цикл нового фрагмента от onCreate()
до onResume()
и уничтожение предыдущего фрагмента от onPause()
до onDestroy()
.
val fragmentManager = supportFragmentManager
val transaction = fragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, FragmentB())
transaction.commit()
remove
Удаляет фрагмент из FragmentManager, что означает, что фрагмент больше не отображается на экране. Однако состояние фрагмента сохраняется в FragmentManager, и его можно восстановить, если это необходимо.
addToBackStack
Добавляет текущую транзакцию фрагментов в стек возврата, что позволяет пользователю вернуться к предыдущему состоянию фрагментов при нажатии кнопки “Назад”.
popBackStack
Удаляет верхний фрагмент из стека возврата. Это приводит к тому, что фрагмент, который был перед ним, становится видимым, а текущий фрагмент удаляется.
// Удаление последнего фрагмента из стека возврата
supportFragmentManager.popBackStack()
// Удаление всех фрагментов до фрагмента с именем "myFragmentName"
supportFragmentManager.popBackStack("myFragmentName", FragmentManager.POP_BACK_STACK_INCLUSIVE)
popBackStackImmediate
Работает аналогично методу popBackStack, но выполняет операцию немедленно, а не асинхронно.
// Немедленное удаление последнего фрагмента из стека возврата
supportFragmentManager.popBackStackImmediate()
// Немедленное удаление всех фрагментов до фрагмента с именем "myFragmentName"
supportFragmentManager.popBackStackImmediate("myFragmentName", FragmentManager.POP_BACK_STACK_INCLUSIVE)
executePendingTransactions
Заставляет FragmentManager немедленно выполнить все ожидающие транзакции. Это отличается от методов commit или commitNow, которые фиксируют транзакции асинхронно или немедленно, но не обязательно выполняют их сразу.
commit
Фиксирует изменения в FragmentTransaction, сделанные до вызова этого метода. Это включает в себя добавление, удаление, замену или изменение фрагментов. Выполняет транзакцию асинхронно. Это значит, что изменения могут быть применены позже, в следующем цикле обновления UI. Если вызвать executePendingTransactions после метода commit
, то транзакция станет синхронной.
commitNow
Выполняет транзакцию синхронно, немедленно фиксируя изменения. Используйте этот метод, если нужно убедиться, что транзакция завершена до выполнения следующего кода.
commitAllowingStateLoss
Фиксирует транзакцию, игнорируя потенциальные потери состояния активити и фрагмента. Это может быть полезно, если состояние не критично и транзакция должна быть выполнена независимо от возможной потери состояния.
Использование commitAllowingStateLoss
приводит к ситуациям такого вида: Пользователь возвращается на активити, которая была уничтожена системой. Пользователь ожидает увидеть UI, который отображался перед тем как он покинул активити, но транзакция с добавлением или удалением фрагмента не сохранилась и пользователь видит пустой экран или активити в неверном состоянии. Хорошей практикой считается использование commit
, а не commitAllowingStateLoss
. Если вы получаете репорты о state loss крэшах, пробуйте решить корень проблемы. Для этого не вызывайте commit
в onPause
или следующих после него методах.
dismiss
Используется для закрытия или удаления фрагмента, который был добавлен с помощью FragmentManager.
dismissNow
Используется для немедленного удаления фрагмента. В отличие от dismiss
, который может быть отложен до завершения текущего цикла событий, dismissNow
выполнит действие сразу же.
dismissAllowingStateLoss
Используется для удаления фрагмента, игнорируя потенциальные потери состояния. Он похож на метод dismiss, но позволяет удалять фрагмент даже если это может привести к потере состояния активити или фрагмента.
Что будет, если закоммитить фрагмент, когда приложение свернуто?
• Transaction будет отложена. Фрагмент-менеджер не будет немедленно обрабатывать транзакцию фрагмента, если приложение находится в состоянии, когда его интерфейс не виден (например, свернуто). Однако транзакция будет сохранена в состоянии “отложенной” и выполнится, когда приложение снова станет активным.
• Transaction может быть отклонена. Если транзакция была выполнена после того, как активность была завершена или уничтожена, то она может не быть применена. Это связано с тем, что состояние активности может быть неактуальным, и попытка обновить UI может привести к исключениям или некорректному отображению.
• Lifecycle состояния: Если приложение находится в фоновом режиме, транзакция фрагмента может быть обработана при следующем восстановлении активности. Однако важно помнить, что операции, влияющие на пользовательский интерфейс, лучше выполнять только когда активность в активном состоянии, чтобы избежать проблем с жизненным циклом.
Как создать Fragment?
• добавить через XML используя FragmentContainerView
.
• добавить программно через FragmentTransaction
.
• создать через FragmentFactory
.
Android Fragment. Вопросы на собесе
- Что такое Fragment? Чем он отличается от Activity?
- Жизненный цикл фрагмента?
- Какие есть способы создать фрагмент?
- Чем Fragment отличается от View?
- Что будет, если мы попытаемся закоммитить фрагмент, когда приложение свернуто?
- Для чего нужен метод commitAllowingStateLoss?
Выполняет транзакцию фрагмента, даже если состояние
Activity
потеряно, что предотвращает исключение при коммите.
- Разница методов add и replace?
Метод
add()
добавляет новый фрагмент поверх существующего, оставляя предыдущий активным и в состоянииresumed
, тогда как методreplace()
заменяет текущий фрагмент, вызывая у него полный жизненный цикл (сonPause()
доonDestroy()
) перед добавлением нового фрагмента.
- Является ли метод FragmentManager.commit() синхронным?
• Да, он синхронный.
• Нет, он асинхронный.
• Такого метода нет.
- Какие методы жизненого цикла фрагмента существуют?
•
oninflate()
•
onResume()
•
onReload()
•
onStart()
- Какой метод жизненного цикла фрагмента вызывается, когда фрагмент больше не виден пользователю?
•
onDetach()
•
onPause()
•
onDestroyView()
•
onStop()
- Какой метод следует использовать для проверки наличия фрагмента в FragmentManager по его тегу?
• locateFragmentByTag
• findFragmentByTag
• searchFragmentByTag
• getFragmentByTag
- В каком методе фрагмент становится доступен Activity?
• onCreate
• onBind
• onAttach
• onStart
- Какой метод жизненного цикла фрагмента вызывается для создания иерархии пользовательского интерфейса?
• onCreateView
• onAttach
• onCreate
• onStart
- Какой из следующих классов используется для работы с фрагментами в Android?
• FragmentController
• FragmentManager
• FragmentHandler
• FragmentActivity
- Какой метод используется для закрытия диалога в Android?
• dismiss
• cancelDialog
• closeDialog
• dismissDialog