Когда Singleton объект инициализируется

Ответ

В Android Singleton инициализируется при первом обращении к нему (ленивая инициализация). Однако есть нюансы:

  1. Обычный Singleton (через getInstance()):
class MySingleton {
    companion object {
        private var instance: MySingleton? = null

        fun getInstance(): MySingleton {
            return instance ?: synchronized(this) {
                instance ?: MySingleton().also { instance = it }
            }
        }
    }
}
  1. Инициализация при объявлении (ранняя инициализация):
object MySingleton {
    init {
        // код инициализации
    }
}

В Android также стоит учитывать:

  • Singleton живет в памяти пока живёт процесс приложения
  • Может быть пересоздан при убийстве и восстановлении процесса
  • Не подходит для хранения данных, которые должны сохраняться между сессиями

Ответ 18+ 🔞

А, слушай, вот эта тема с синглтонами в Android — это вообще отдельная песня, блядь. Как будто на дворе 2002-й год, и все до сих пор спорят, как правильно. Но тут есть свои подводные камни, ёпта.

Вот смотри, классический подход — это ленивая инициализация. То есть, объект создаётся только тогда, когда ты впервые за ним пришёл, как последний алкаш за бутылкой в пять утра. Выглядит это примерно так:

class MySingleton {
    companion object {
        private var instance: MySingleton? = null

        fun getInstance(): MySingleton {
            return instance ?: synchronized(this) {
                instance ?: MySingleton().also { instance = it }
            }
        }
    }
}

Видишь эту конструкцию? synchronized — это чтобы два потока не вломились одновременно и не создали два экземпляра, а то будет тебе не синглтон, а пиздопроебина полная. Это как если бы в туалетную кабинку пытались зайти сразу два человека — ничего хорошего не выйдет.

А есть вариант для тех, кому терпения ноль ебать, и кто хочет всё и сразу. Ранняя инициализация, через object:

object MySingleton {
    init {
        // код инициализации
    }
}

Вот это object — штука мощная. Объект создастся сразу, как только класс загрузится. Удобно, быстро, но если он тяжёлый и жрёт ресурсы при создании, а нужен тебе не сразу — то это, блядь, как таскать с собой на свидание чемодан без ручки: и бросить жалко, и нести тяжело.

Теперь самое важное, что многие забывают, а потом охуевают. Синглтон в Android живёт, пока живёт процесс приложения. Это не волшебная палочка для хранения данных навечно. Если система прибьёт твой процесс из-за нехватки памяти (а она это любит делать), а потом восстановит — твой синглтон накроется медным тазом и создастся заново. Всё, что было в его полях — капут. Поэтому хранить в нём состояние, которое должно пережить смерть процесса — это идея уровня «хуй с горы». Для этого есть SharedPreferences, база данных или другие персистентные хранилища.

Короче, синглтон — это инструмент, а не серебряная пуля. Используй с умом, а не тыкай его везде, куда попало, и будет тебе хиросима.