Может ли Context быть null во фрагменте
Что проверяют
Понимаете ли вы, что у фрагмента два жизненных цикла, самого фрагмента и его view, и что Context привязан к первому. Следом обычно спрашивают, чем requireContext() лучше проверки на null и почему отложенный колбэк роняет приложение.
Как отвечать
Да, может. В Kotlin свойство context имеет тип Context?, в Java getContext() помечен @Nullable. Контекст есть у фрагмента от onAttach() до onDetach(), вне этого окна он равен null, как и activity.
Где это случается на практике:
- асинхронный колбэк: сетевой ответ,
postDelayed, подписка RxJava вернулись, когда пользователь уже ушёл с экрана и фрагмент отсоединён; - обращение до attach: код в конструкторе или в инициализаторе свойства фрагмента, когда контекста ещё нет;
- фрагмент в back stack: здесь наоборот, контекст на месте, но после
onDestroyView()нет view, иbindingуказывает на уничтоженную разметку.
Как защищаться. requireContext() возвращает не-null или бросает IllegalStateException с понятным сообщением. Его место там, где контекст гарантирован: onViewCreated(), onResume(), обработчики кликов. В асинхронном коде правильнее не проверять, а не допускать: запускать работу в viewLifecycleOwner.lifecycleScope, собирать потоки через repeatOnLifecycle(Lifecycle.State.STARTED), тогда корутина отменится вместе с view. Если объекту нужен контекст надолго, передавайте applicationContext, а не Activity.
Где спотыкаются
Ставят requireContext() в колбэк сети и считают проблему решённой. NPE просто сменился на IllegalStateException, падение осталось.
Путают циклы фрагмента и view. Запуск в lifecycleScope вместо viewLifecycleOwner.lifecycleScope оставляет корутину живой, когда фрагмент ушёл в back stack, и она пишет в мёртвый binding.
Сохраняют контекст в поле синглтона или долгоживущего объекта. Отсоединённый фрагмент уже не нужен, а Activity продолжает висеть в памяти, и LeakCanary покажет эту утечку первой.