Как отобразить Fragment в Activity в Android
Что проверяют
Знаете ли вы современный способ работы с фрагментами и понимаете ли, что Activity пересоздаётся. Следом почти всегда спрашивают, что будет при повороте экрана и как передать во фрагмент параметры.
Как отвечать
Контейнер в разметке это FragmentContainerView, а не FrameLayout и не устаревший тег <fragment>: он правильно работает с анимациями переходов. Показать фрагмент можно двумя способами:
- статически: атрибут
android:nameс полным именем класса уFragmentContainerView, фрагмент создаётся вместе с разметкой; - динамически: транзакцией через
supportFragmentManager, с fragment-ktx так:
if (savedInstanceState == null) {
supportFragmentManager.commit {
setReorderingAllowed(true)
replace<ProfileFragment>(R.id.container, args = bundleOf("userId" to id))
}
}Проверка savedInstanceState == null обязательна: после поворота FragmentManager сам восстанавливает фрагменты, и без неё появится второй экземпляр поверх первого.
Что ещё стоит сказать:
- аргументы через
Bundle: фрагмент пересоздаётся через пустой конструктор, параметры в конструкторе после поворота потеряются. Зависимости передают черезFragmentFactoryили Hilt; addToBackStack(name): без него «Назад» закроет Activity, а не вернёт прошлый фрагмент;- состояние: транзакция после
onSaveInstanceStateбросаетIllegalStateException, аcommitAllowingStateLossпрячет проблему, но не решает её; - связь с Activity: общий
ViewModelчерезactivityViewModels()или Fragment Result API, а не приведениеrequireActivity() as MainActivity.
При сложной навигации берут Navigation Component с NavHostFragment, а на Compose фрагменты часто не нужны.
Где спотыкаются
Добавляют фрагмент в onCreate без проверки savedInstanceState. После поворота на экране два экземпляра и двойные сетевые запросы.
Держат binding после onDestroyView. Вью живёт меньше фрагмента в back stack, и это утечка; подписки привязывают к viewLifecycleOwner.
Путают add и replace. При add прежний фрагмент остаётся под новым, держит память, а клики проходят к нему насквозь, если у нового нет фона.