Когда у фрагмента есть контекст, а когда его нет
Что проверяют
Знаете ли вы жизненный цикл фрагмента настолько, чтобы не ронять приложение из асинхронного колбэка. Следом обычно спрашивают, чем getContext() отличается от requireContext() и чем жизненный цикл фрагмента отличается от жизненного цикла его view.
Как отвечать
Контекст фрагмента это контекст хоста, обычно активити. Фрагмент получает его при прикреплении и теряет при откреплении:
- до
onAttach(Context): в конструкторе и в полях, которые инициализируются при создании, контекста нет.onAttach(Activity)устарел, актуальная версия принимаетContext; - от
onAttach()доonDetach(): контекст доступен вonCreate(),onCreateView(),onViewCreated(),onStart()и дальше.onActivityCreated()в AndroidX объявлен устаревшим, код из него переносят вonViewCreated(); - после
onDetach():getContext()возвращаетnull, аrequireContext()иrequireActivity()бросаютIllegalStateException.
Проверить состояние можно через isAdded(), но правильнее не допускать такой ситуации. Корутины запускают в viewLifecycleOwner.lifecycleScope, а сбор Flow оборачивают в repeatOnLifecycle(Lifecycle.State.STARTED), тогда работа отменяется вместе с view.
Хорошо добавить нюанс про back stack. При замене фрагмента с addToBackStack() вызывается onDestroyView(), но фрагмент остаётся прикреплённым: контекст есть, view нет. Поэтому ссылку на binding обнуляют в onDestroyView().
При повороте экрана активити по умолчанию пересоздаётся, а FragmentManager создаёт новый экземпляр фрагмента. Старый экземпляр откреплён, и колбэк, который держит ссылку на него, получит null вместо контекста.
Где спотыкаются
Вызывают requireContext() в ответе сети или в таймере, когда пользователь уже ушёл с экрана. Приложение падает с IllegalStateException, хотя многие ожидают NullPointerException.
Запускают корутину в lifecycleScope фрагмента, а не view, и обновляют view, которой уже нет, пока фрагмент лежит в back stack.
Сохраняют активити или контекст фрагмента в синглтоне или во ViewModel. Это утечка всей активити, долгоживущим объектам нужен applicationContext.