На этом шаге мы рассмотрим организацию такой инициализации.
Класс Activity в Android представляет экран вашего приложения. Вы не контролируете момент, когда именно будет вызван конструктор Activity. Зато известно, что самая ранняя точка выполнения - это функция с именем onCreate(). Если нельзя инициализировать свойства во время создания экземпляра, то когда это можно сделать?
Это та ситуация, когда важное значение приобретает поздняя инициализация, и это больше, чем просто нарушение правил инициализации компилятора Kotlin.
В любое объявление var-свойства можно добавить ключевое слово lateinit. Тогда компилятор Kotlin позволит отложить инициализацию свойства до того момента, когда такая возможность появится.
class Player { lateinit var alignment: String fun determineFate() { alignment = "Good" } fun proclaimFate() { if (::alignment.isInitialized) println(alignment) } }
Это полезный инструмент, но его следует применять с осторожностью. Если переменная с поздней инициализацией получит начальное значение до первого обращения к ней, проблем не будет. Но если сослаться на такое свойство до его инициализации, вас ждет неприятное исключение UninitializedPropertyAccessException. Эту проблему можно решить, использовав тип с поддержкой null, но тогда вам придется обрабатывать возможное значение null по всему коду, что очень утомительно. Получив начальное значение, переменные с поздней инициализацией будут работать так же, как другие переменные.
Ключевое слово lateinit действует как негласный договор: "Я обязуюсь инициализировать эту переменную до первой попытки обратиться к ней". Kotlin предоставляет инструмент для проверки факта инициализации таких переменных: метод isInitialized, показанный в примере выше. Вы можете вызывать isInitialized каждый раз, когда есть сомнения, что переменная lateinit инициализирована, чтобы избежать UninitializedPropertyAccessException.
Тем не менее isInitialized следует использовать экономно - например, не следует добавлять эту проверку к каждой переменной с поздней инициализацией. Если вы используете isInitialized слишком часто, это, скорее всего, означает, что лучше использовать тип с поддержкой null.
На следующем шаге мы рассмотрим отложенную инициализацию.