Что такое nullable типы в Kotlin и как с ними работать
Что проверяют
Умеете ли вы жить с тем, что значительная часть платформы написана на Java и нужное значение существует не всегда: контекста у фрагмента может не быть, разметка может быть уничтожена, аргумент из Intent может не прийти.
Как отвечать
База такая же, как в любом коде на Kotlin: тип не принимает null, пока не написан вопросительный знак, дальше работают ?., ?:, ?.let и as?. Интереснее то, что специфично для платформы.
Многие методы SDK возвращают пустое значение по существу дела: дополнительные поля Intent, сохранённое состояние, контекст фрагмента вне присоединённого состояния. Там, где Java-код не размечен аннотациями допустимости null, тип приходит платформенным, и компилятор не заставит вас проверить его. Такие значения лучше сразу приводить к необязательному типу и обрабатывать явно.
Отдельная тема это привязка разметки во фрагменте: поле обнуляют в onDestroyView, а доступ идёт через свойство, поэтому отложенный колбэк рискует прийти уже после уничтожения представления.
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}Где спотыкаются
Не знают про ограничение умного приведения типа. Проверка на пустоту не поможет, если свойство объявлено через var: между проверкой и использованием его мог изменить другой поток, и компилятор потребует локальную копию или ?.let.
Держат двойной восклицательный знак там, где сценарий нормальный. Экран открыли без аргументов, пользователь ушёл до ответа сети, система пересоздала процесс: это обычные состояния, и на них отвечают значением по умолчанию или пустым экраном, а не падением.
Обращаются к разметке или контексту из колбэка, пережившего представление. Ответ приходит после onDestroyView, свойство с принудительным разыменованием бросает исключение, и краш выглядит случайным. Лечится привязкой работы к жизненному циклу, а не проверками в каждом колбэке.