Fragment

https://developer.android.com/guide/fragments
https://developer.android.com/guide/fragments/lifecycle
https://developer.android.com/guide/fragments/communicate
https://developer.android.com/guide/fragments/fragmentmanager
https://developer.android.com/guide/fragments/transactions
https://developer.android.com/guide/fragments/create
17.10.2022https://habr.com/ru/companies/tbank/articles/693794/
04.10.2022https://habr.com/ru/companies/tbank/articles/691344/
26.09.2022https://habr.com/ru/companies/tbank/articles/690134/
14.09.2022https://habr.com/ru/companies/tbank/articles/688222/

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. Вопросы на собесе
  1. Что такое Fragment? Чем он отличается от Activity?
  1. Жизненный цикл фрагмента?
  1. Какие есть способы создать фрагмент?
  1. Чем Fragment отличается от View?
  1. Что будет, если мы попытаемся закоммитить фрагмент, когда приложение свернуто?
  1. Для чего нужен метод commitAllowingStateLoss?

    Выполняет транзакцию фрагмента, даже если состояние Activity потеряно, что предотвращает исключение при коммите.

  1. Разница методов add и replace?

    Метод add() добавляет новый фрагмент поверх существующего, оставляя предыдущий активным и в состоянии resumed, тогда как метод replace() заменяет текущий фрагмент, вызывая у него полный жизненный цикл (с onPause() до onDestroy()) перед добавлением нового фрагмента.

  1. Является ли метод FragmentManager.commit() синхронным?

    Да, он синхронный.

    Нет, он асинхронный.

    Такого метода нет.

  1. Какие методы жизненого цикла фрагмента существуют?

    oninflate()

    onResume()

    onReload()

    onStart()

  1. Какой метод жизненного цикла фрагмента вызывается, когда фрагмент больше не виден пользователю?

    onDetach()

    onPause()

    onDestroyView()

    onStop()

  1. Какой метод следует использовать для проверки наличия фрагмента в FragmentManager по его тегу?

    locateFragmentByTag

    findFragmentByTag

    searchFragmentByTag

    getFragmentByTag

  1. В каком методе фрагмент становится доступен Activity?

    onCreate

    onBind

    onAttach

    onStart

  1. Какой метод жизненного цикла фрагмента вызывается для создания иерархии пользовательского интерфейса?

    onCreateView

    onAttach

    onCreate

    onStart

  1. Какой из следующих классов используется для работы с фрагментами в Android?

    FragmentController

    FragmentManager

    FragmentHandler

    FragmentActivity

  1. Какой метод используется для закрытия диалога в Android?

    dismiss

    cancelDialog

    closeDialog

    dismissDialog