Как реализовать синглтон в Kotlin
Что проверяют
Знаете ли вы, что в Kotlin синглтон делается одним словом object, и понимаете ли, что происходит под капотом и чем глобальное состояние опасно на Android. Следом спрашивают про синглтон с параметром, обычно с Context, и про то, почему в проекте вместо этого используют DI.
Как отвечать
Основные варианты с оценкой каждого:
object: компилируется в класс с приватным конструктором и статическим полемINSTANCE. Экземпляр создаётся при первом обращении, во время инициализации класса, а JVM гарантирует, что это произойдёт ровно один раз и потокобезопасно. Ниsynchronized, ни двойной проверки не нужно;by lazy: подходит для отложенного создания тяжёлого поля. Режим по умолчаниюLazyThreadSafetyMode.SYNCHRONIZED, есть ещёPUBLICATIONиNONEдля случаев, где многопоточность исключена;- синглтон с параметром: у
objectнет конструктора, поэтому пишутcompanion objectс@Volatile private var instanceи двойной проверкой внутриsynchronized(this). Классический пример:getDatabase(context)у Room. Важно сохранятьcontext.applicationContext, а не пришедшуюActivity; - DI вместо ручного синглтона: в Hilt это
@Singletonна классе или провайдере в модуле, установленном вSingletonComponent, в Koinsingle { }. Экземпляр один на приложение, но зависимость передаётся явно и подменяется в тестах.
Сильный ответ заканчивается мыслью, что object хорош для stateless-утилит и констант, а всё, что держит состояние или ресурсы (база, сеть, репозитории), лучше отдать DI-контейнеру.
Где спотыкаются
Кладут в синглтон Activity, View или Fragment. Объект живёт столько же, сколько процесс, и держит ссылку на уничтоженный экран: классическая утечка памяти, которую сразу покажет LeakCanary.
Пишут двойную проверку без @Volatile. Другой поток может увидеть ссылку на ещё не до конца сконструированный объект.
Хранят в object пользовательское состояние и рассчитывают на него после возврата в приложение. Система может убить процесс в фоне, синглтон создастся заново пустым, а экран восстановится из savedInstanceState и упадёт на отсутствующих данных.