Можно ли создать Singleton с параметризованным конструктором в Kotlin
Что проверяют
Понимаете ли вы, что object в Kotlin это уже готовый синглтон, и что делать, когда экземпляру нужен параметр. На Android за этим вопросом почти всегда стоит второй: как вы протаскиваете Context и не течёт ли у вас память.
Как отвечать
Ключевым словом object синглтон с параметрами не создать: конструктора у него нет. Компилируется он в класс со статическим полем INSTANCE, которое инициализируется лениво и потокобезопасно при первом обращении.
Если параметр всё же нужен, вариантов три:
- приватный конструктор плюс
companion objectс фабрикой и двойной проверкой; - отложенная инициализация одним вызовом из
Application.onCreate(), дальше только чтение; - не делать синглтон руками, а отдать время жизни контейнеру внедрения зависимостей (Hilt, Dagger, Koin), где параметры приходят как зависимости графа.
class Repo private constructor(private val ctx: Context) {
companion object {
@Volatile private var instance: Repo? = null
fun get(context: Context): Repo =
instance ?: synchronized(this) {
instance ?: Repo(context.applicationContext).also { instance = it }
}
}
}Где спотыкаются
Пишут фабрику без @Volatile и synchronized. Два потока проходят проверку на null одновременно, создаются два объекта, и один из них тихо теряется вместе с записанным в него состоянием.
Кладут в синглтон активность или её контекст. Объект живёт до смерти процесса, активность после поворота экрана не собирается, память течёт. Хранить можно только applicationContext.
Не проговаривают, что параметры второго вызова игнорируются. Вызов с одним аргументом, а потом с другим вернёт тот же объект с первым значением. Это либо осознанное поведение, либо признак того, что здесь нужен вовсе не синглтон, а обычный объект со временем жизни экрана.