Как долго живет зависимость, помеченная как Singleton в Dagger
Что проверяют
Понимаете ли вы, что @Singleton в Dagger это обычная аннотация скоупа, а не глобальный синглтон на процесс. Следом спрашивают, что будет, если создать компонент дважды, и как это устроено в Hilt.
Как отвечать
Короткий ответ: зависимость со скоупом живёт ровно столько, сколько живёт экземпляр компонента, который её создал. Компонент кеширует объект у себя и отдаёт его всем, кто просит в пределах этого компонента. Когда на компонент не остаётся ссылок, его вместе с зависимостями забирает сборщик мусора. Про жизненный цикл Activity и Fragment Dagger ничего не знает.
Дальше раскройте следствия:
- где хранится компонент: если
AppComponentсоздаётся вApplication.onCreate()и лежит в полеApplication, «синглтон» живёт до смерти процесса. Если компонент по ошибке собирать в Activity, экземпляр будет свой у каждой Activity; - правило скоупов: скоупная привязка живёт только в компоненте с тем же скоупом. Положить
@Singletonв компонент с@ActivityScopeне выйдет, это ошибка компиляции. Сабкомпонент не может повторять скоуп предка; - без скоупа: новый экземпляр на каждую инъекцию.
@Reusableразрешает кешировать, но не гарантирует один экземпляр; - Hilt:
@Singletonпривязан кSingletonComponentи живёт с приложением,@ActivityRetainedScopedпереживает поворот экрана,@ViewModelScopedживёт с ViewModel,@ActivityScopedумирает вместе с Activity; - смерть процесса: система убивает процесс в фоне, и состояние синглтонов пропадает. Восстанавливать его нужно из
SavedStateHandleили постоянного хранилища.
Где спотыкаются
Говорят, что @Singleton гарантирует один экземпляр на приложение. Два экземпляра компонента дадут два разных «синглтона».
Держат в синглтоне ссылку на Activity или её Context. Activity уничтожена, а синглтон держит её до конца процесса: классическая утечка. Нужен applicationContext.
Хранят в синглтоне сессию пользователя и забывают сбросить её при выходе из аккаунта, и следующий пользователь видит чужие данные.