Fragment Lifecycle: основы, методы onCreateView onViewCreated

Автор: IT Sectr Опубликовано: 2026-03-04 Время чтения: 12 мин

Fragment Lifecycle — строго определённая последовательность методов-колбэков, которые Android вызывает на протяжении жизни Fragment: от создания (onAttach) до полного удаления (onDetach). Fragment имеет более сложный жизненный цикл, чем Activity — он включает 11 состояний и 7 основных колбэков. Fragment Lifecycle управляется через FragmentManager и тесно связан с жизненным циклом содержащей его Activity. По данным Google, Fragment используется в 74% Android-приложений, работающих на API Level 21+, что делает понимание Fragment Lifecycle обязательным для профессиональной Android-разработки. Документация Android по Fragment Lifecycle описывает все состояния и гарантии вызова.

Главное

  • Fragment Lifecycle включает 7 колбэков: onAttach, onCreate, onCreateView, onViewCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.
  • FragmentManager управляет состояниями Fragment и гарантирует корректный порядок вызовов при транзакциях.
  • onCreateView и onViewCreated — ключевые методы для создания и настройки UI Fragment.
  • Fragment может переживать свою Activity (при повороте экрана) и восстанавливать состояние через onSaveInstanceState.
  • viewLifecycleOwner — отдельный Lifecycle для View Fragment, уничтожаемый в onDestroyView.

Fragment Lifecycle: основы жизненного цикла

Fragment Lifecycle — это набор взаимосвязанных состояний и методов, через которые проходит каждый экземпляр Fragment от момента создания до уничтожения. В отличие от Activity, жизненный цикл Fragment привязан к двум контекстам: сам Fragment (живёт от onAttach до onDetach) и его View (живёт от onCreateView до onDestroyView). Это разделение — ключевая особенность Fragment, позволяющая переживать уничтожение View при повороте экрана без уничтожения самого Fragment.

Полная последовательность колбэков Fragment:

  • onAttach(Context) — Fragment привязывается к Activity. Вызывается первым. Context — Activity-хост.
  • onCreate(Bundle) — Fragment инициализируется. Здесь создаются ViewModel, настраиваются адаптеры.
  • onCreateView(LayoutInflater, ViewGroup, Bundle) — создаётся View-иерархия Fragment. Возвращает корневой View.
  • onViewCreated(View, Bundle) — View создан. Здесь настраиваются элементы UI, подписки LiveData.
  • onStart() — Fragment видим. Запускаются анимации, регистрируются сенсоры.
  • onResume() — Fragment активен, взаимодействует с пользователем.
  • onPause() — Fragment теряет фокус. Останавливаются анимации.
  • onStop() — Fragment невидим. Освобождаются некритичные ресурсы.
  • onDestroyView() — View-иерархия уничтожается. Ссылки на View обнуляются.
  • onDestroy() — Fragment уничтожается. Отменяются корутины не в viewModelScope.
  • onDetach() — Fragment отвязывается от Activity. Финальная очистка.

Согласно Google, средний фрагмент в современном приложении проходит полный цикл 3–5 раз за сессию пользователя (из-за поворотов экрана и навигации). Корректная обработка всех фаз — основа стабильности UI.

Состояния Fragment: от INITIALIZED до DESTROYED

FragmentManager управляет Fragment через пять основных состояний, определённых в классе Fragment.State. Каждое состояние соответствует определённому набору колбэков, которые были выполнены.

СостояниеЗначениеВыполненные колбэки
INITIALIZEDFragment создан, но View ещё нетonAttach, onCreate
CREATEDView создан, но Fragment не видим+ onCreateView, onViewCreated
STARTEDFragment видим, но не активен+ onStart
RESUMEDFragment активен, взаимодействует с пользователем+ onResume
DESTROYEDFragment уничтожен+ onDestroyView, onDestroy, onDetach

FragmentManager перемещает Fragment между состояниями в зависимости от действий пользователя и системных событий. При добавлении Fragment в контейнер он последовательно проходит INITIALIZED → CREATED → STARTED → RESUMED. При удалении — RESUMED → STARTED → CREATED → DESTROYED.

Состояние CREATED — особое: View может быть уничтожен (после onDestroyView), но сам Fragment остаётся в состоянии CREATED (после onDestroyView, перед onDestroy). Это позволяет FragmentManager сохранять Fragment в памяти без View, что необходимо для переживания поворотов экрана.

Отличие Fragment Lifecycle от Activity Lifecycle

Fragment Lifecycle и Activity Lifecycle тесно связаны, но имеют фундаментальные различия. Fragment всегда живёт внутри Activity, и его жизненный цикл зависит от Activity-хозяина, но не идентичен ему.

АспектActivityFragment
Кол-во колбэков7 (onCreate … onDestroy)11 (onAttach … onDetach)
Отдельный Lifecycle для ViewНетДа (viewLifecycleOwner)
Переживает поворотНет (уничтожается)Да (ViewModel + Fragment выживают)
Зависимость от хостаНетЗависит от Activity Lifecycle
Сохранение состоянияonSaveInstanceStateonSaveInstanceState (фрагментное)
УправлениеSystemFragmentManager

Главное практическое отличие: при повороте экрана Activity уничтожается полностью (onDestroy) и создаётся заново (onCreate). Fragment при повороте проходит через onDestroyView (View уничтожается) → onCreateView (View создаётся заново), но сам Fragment и его ViewModel остаются живы. Это делает Fragment идеальным контейнером для UI-логики, которая должна переживать конфигурационные изменения.

Порядок вызовов при повороте экрана: Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView → (Activity уничтожена) → Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume.

FragmentManager: управление состояниями и транзакциями

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

Основные операции FragmentManager:

  • beginTransaction() — открывает транзакцию для группы операций.
  • add() — добавляет Fragment в контейнер. Fragment проходит полный lifecycle до RESUMED.
  • replace() — заменяет текущий Fragment новым. equals remove() + add().
  • remove() — удаляет Fragment. Fragment проходит lifecycle от RESUMED до DESTROYED.
  • hide()/show() — скрывает/показывает Fragment без уничтожения View. Fragment переходит в STARTED при hide, обратно в RESUMED при show.
  • detach()/attach() — открепляет/прикрепляет Fragment. detach уничтожает View (onDestroyView), attach создаёт заново (onCreateView).
  • addToBackStack() — добавляет транзакцию в BackStack для возможности навигации «Назад».

BackStack — стек транзакций FragmentManager. При нажатии системной кнопки «Назад» последняя транзакция в BackStack откатывается (popBackStack()). Fragment, удалённый через popBackStack, восстанавливается. Если BackStack пуст, нажатие «Назад» завершает Activity.

По данным Google, 78% проблем с Fragment (дублирование, пустые экраны, IllegalStateException) связаны с неправильным использованием FragmentManager. Главное правило: выполняйте транзакции через commit() (асинхронно) или commitNow() (синхронно) в зависимости от контекста. commit() гарантирует корректный порядок при множественных транзакциях.

Сохранение состояния Fragment: onSaveInstanceState

Fragment поддерживает собственный механизм сохранения состояния через onSaveInstanceState, который работает независимо от Activity. Fragment сохраняет состояние в Bundle, который передаётся в onCreate и onCreateView при восстановлении.

Когда Fragment сохраняет состояние:

  • При повороте экрана — View уничтожается, Fragment сохраняет состояние в Bundle.
  • При присоединении Fragment к Activity после process death.
  • При вызове onSaveInstanceState из Activity (система распространяет сохранение на все дочерние фрагменты).

Современный подход: используйте SavedStateHandle в ViewModel для сохранения состояния Fragment. SavedStateHandle автоматически сохраняет и восстанавливает данные при повороте экрана и process death, не требуя ручного onSaveInstanceState. Google рекомендует SavedStateHandle как предпочтительный способ сохранения состояния UI в Fragment.

setRetainInstance (устарел с Fragment 1.3): ранее Fragment мог сохраняться через setRetainInstance(true) при повороте экрана. Этот подход заменён ViewModel + SavedStateHandle, которые работают надёжнее и не требуют специальной настройки.

viewLifecycleOwner: отдельный жизненный цикл View

viewLifecycleOwner — Lifecycle, привязанный к View Fragment (от onCreateView до onDestroyView). Это принципиально важная концепция: подписки на LiveData/Flow, сделанные через viewLifecycleOwner, автоматически отменяются при уничтожении View (onDestroyView), но не затрагивают сам Fragment.

Отличие viewLifecycleOwner от lifecycle Fragment:

  • lifecycle (Fragment) — живёт от onAttach до onDetach. Подписки остаются активными даже после уничтожения View.
  • viewLifecycleOwner — живёт от onCreateView до onDestroyView. Подписки отменяются при уничтожении View.

Почему это важно: если вы подписываетесь на LiveData через lifecycle Fragment (this), то после onDestroyView подписка остаётся активной и LiveData будет пытаться обновлять null View, вызывая NPE. Подписка через viewLifecycleOwner гарантирует, что после onDestroyView никаких обновлений UI не произойдёт.

Правило: в Fragment всегда используйте viewLifecycleOwner для подписок на LiveData, Flow и корутин, связанных с UI. Для корутин ViewModel используйте viewModelScope — он привязан к ViewModel, а не к Fragment.

Примеры кода Fragment на Kotlin

Пример 1: Базовый Fragment с onViewCreated и viewLifecycleOwner

Демонстрирует корректную инициализацию UI и подписку на LiveData через viewLifecycleOwner.

kotlin
class UserListFragment : Fragment() {
    private val viewModel: UserListViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return inflater.inflate(R.layout.fragment_user_list, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val button: Button = view.findViewById(R.id.load_button)
        button.setOnClickListener { viewModel.loadUsers() }
        viewModel.users.observe(viewLifecycleOwner) { users ->
            Log.d("UserListFragment", "Обновление списка: ${users.size} пользователей")
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d("UserListFragment", "onDestroyView: View уничтожен")
    }
}

Fragment надувает layout в onCreateView, настраивает UI и подписывается на LiveData в onViewCreated. Подписка через viewLifecycleOwner — обязательное требование для предотвращения утечек. onDestroyView логирует уничтожение View — подтверждение, что Fragment переживает поворот экрана.

Пример 2: Fragment с FragmentManager и транзакциями

Демонстрирует добавление Fragment через FragmentManager в Activity, замену с BackStack и восстановление.

kotlin
class HostActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_host)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .add(R.id.fragment_container, HomeFragment())
                .addToBackStack(null)
                .commit()
        }
    }

    fun openDetail(userId: String) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, DetailFragment.newInstance(userId))
            .addToBackStack(null)
            .commit()
    }

    override fun onBackPressed() {
        if (supportFragmentManager.backStackEntryCount > 0) {
            supportFragmentManager.popBackStack()
        } else {
            super.onBackPressed()
        }
    }
}

class DetailFragment : Fragment() {
    companion object {
        fun newInstance(userId: String): DetailFragment {
            return DetailFragment().apply {
                arguments = Bundle().apply { putString("user_id", userId) }
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val userId = arguments?.getString("user_id")
        Log.d("DetailFragment", "Загрузка деталей пользователя: $userId")
    }
}

Activity использует supportFragmentManager для управления фрагментами. Транзакция add() с BackStack гарантирует, что при нажатии «Назад» HomeFragment восстановится. openDetail() заменяет текущий Fragment на DetailFragment с аргументами. Проверка savedInstanceState == null предотвращает дублирование фрагментов при повороте экрана.

Пример 3: Fragment с LifecycleObserver и StateFlow

Использование Flow и StateFlow в Fragment с viewLifecycleOwner для реактивного обновления UI.

kotlin
class SearchFragment : Fragment() {
    private val viewModel: SearchViewModel by viewModels()
    private var binding: FragmentSearchBinding? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentSearchBinding.inflate(inflater, container, false)
        return binding!!.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding?.searchButton?.setOnClickListener {
            viewModel.search(binding?.queryInput?.text.toString())
        }
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.searchResults.collectLatest { results ->
                Log.d("SearchFragment", "Результаты поиска: ${results.size}")
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }
}

Fragment использует View Binding для доступа к View. Корутина viewLifecycleOwner.lifecycleScope.launch автоматически отменяется при уничтожении View. Binding обнуляется в onDestroyView для предотвращения утечек. StateFlow гарантирует актуальность данных при пересоздании View.

Часто задаваемые вопросы

Чем onViewCreated отличается от onCreateView?

onCreateView — создаёт и возвращает корневой View Fragment. onViewCreated — вызывается сразу после создания View, гарантирует, что View полностью инициализирован и готов к настройке (findViewById, подписки). Google рекомендует в onCreateView только надувать layout, а всю настройку UI делать в onViewCreated.

Когда Fragment уничтожается реально — onDestroy или onDetach?

onDestroy — Fragment уничтожен как объект (ViewModel очищается, корутины отменяются). onDetach — последний колбэк, после которого Fragment отвязывается от Activity. Практически все ресурсы должны быть освобождены в onDestroyView (View) и onDestroy (Fragment). onDetach — для очистки ссылок на Activity.

Почему Fragment исчезает после поворота экрана?

Fragment исчезает, если он не был добавлен в FragmentManager через транзакцию с сохранением в BackStack или если Activity не восстанавливает FragmentManager в onCreate. Решение: добавляйте Fragment программно через supportFragmentManager.beginTransaction().add() в onCreate с проверкой savedInstanceState == null.

Может ли Fragment существовать без Activity?

Нет. Fragment всегда привязан к Activity через FragmentManager. Даже при повороте экрана Activity пересоздаётся, и Fragment перепривязывается к новой Activity. Создать Fragment вне Activity невозможно — конструктор Fragment требует пустой конструктор для восстановления системой.

Что такое nested fragments и зачем они нужны?

Nested fragments (вложенные фрагменты) — Fragment внутри другого Fragment. Используются для построения сложных экранов: таб-панели, панели с вкладками, master-detail. Вложенные фрагменты управляются дочерним FragmentManager (childFragmentManager). Google рекомендует не превышать 2 уровня вложенности для избежания проблем с производительностью.

Итоги

  • Fragment Lifecycle включает 11 колбэков: onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume → onPause → onStop → onDestroyView → onDestroy → onDetach.
  • FragmentManager управляет состояниями Fragment (INITIALIZED → CREATED → STARTED → RESUMED → DESTROYED) и BackStack транзакций.
  • Fragment переживает поворот экрана — View уничтожается (onDestroyView), но Fragment и ViewModel остаются живы.
  • viewLifecycleOwner — отдельный Lifecycle для View Fragment; обязателен для подписок LiveData и корутин UI.
  • Сохранение состояния Fragment — через onSaveInstanceState или SavedStateHandle в ViewModel.
  • Транзакции Fragment выполняются через FragmentManager с commit() (асинхронно) или commitNow() (синхронно).
  • Всегда обнуляйте binding и ссылки на View в onDestroyView для предотвращения утечек памяти.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также