← Назад к вопросам

Как долго живет зависимость помеченная аннотацией Singleton в Dagger

2.0 Middle🔥 201 комментариев
#Dependency Injection#Архитектура и паттерны

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Время жизни Singleton в Dagger

В Dagger 2 аннотация @Singleton определяет время жизни зависимости в рамках одного компонента (Component). Это ключевой момент: "долгота жизни" привязана не к приложению в целом, а к конкретному экземпляру компонента, который её предоставляет.

Основной принцип

  • @Singleton — это scope (область видимости/времени жизни). Она не создаёт синглтон в классическом понимании (как статическое поле в классе). Вместо этого Dagger гарантирует, что в рамках одного экземпляра компонента будет создан и переиспользован ровно один экземпляр помеченного класса.
  • Зависимость живет столько же, сколько живет компонент. Когда компонент уничтожается (становится доступным для сборщика мусора), все его "синглтон"-зависимости также могут быть собраны. В Android это напрямую связано с жизненным циклом Activity, Fragment или Application.

Практические примеры в Android

1. Singleton в рамках ApplicationComponent

Это самый распространённый и "долгоживущий" случай.

// Модуль
@Module
class AppModule {
    @Singleton
    @Provides
    fun provideHeavyDependency(): HeavyDependency {
        return HeavyDependency()
    }
}

// Компонент, привязанный к жизненному циклу Application
@Singleton
@Component(modules = [AppModule::class])
interface ApplicationComponent {
    fun inject(activity: MainActivity)
    fun getHeavyDependency(): HeavyDependency
}

// В кастомном классе Application
class MyApp : Application() {
    lateinit var appComponent: ApplicationComponent

    override fun onCreate() {
        super.onCreate()
        appComponent = DaggerApplicationComponent.create()
    }
}

Время жизни: Зависимость HeavyDependency создается при первой необходимости после построения ApplicationComponent и живет до тех пор, пока живет объект appComponent, то есть, практически, всё время жизни приложения (пока процесс не будет убит). Это максимально возможное время жизни для @Singleton в Android.

2. Singleton в рамках ActivityComponent (или другого подкомпонента)

Здесь поведение меняется кардинально.

// Допустим, есть Scope для Activity
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class ActivityScope

// Модуль Activity
@Module
class ActivityModule {
    @ActivityScope // Или @Singleton, если компонент Activity изолирован
    @Provides
    fun provideActivityScopedDependency(): ActivityScopedDep {
        return ActivityScopedDep()
    }
}

// Подкомпонент для Activity
@ActivityScope
@Subcomponent(modules = [ActivityModule::class])
interface ActivityComponent {
    fun inject(fragment: MyFragment)
}

Время жизни: Если @Singleton (или кастомный @ActivityScope) используется в модуле ActivityModule, а компонент ActivityComponent создается при старте Activity и не сохраняется между пересозданиями, то зависимость будет жить только пока жива эта конкретная Activity. При повороте экрана и пересоздании Activity будет создан новый компонент и, соответственно, новый экземпляр "синглтона".

Важные выводы и нюансы

  1. Иерархия компонентов: Если ActivityComponent является подкомпонентом ApplicationComponent, то зависимость, помеченная @Singleton в ApplicationComponent, будет единой для всех Activity. ActivityComponent будет запрашивать её у родительского компонента. В этом случае время жизни действительно равно времени жизни приложения.

  2. Ленивая инициализация (по умолчанию): Зависимости в Dagger создаются лениво (Lazy initialization) в момент первого обращения к ним через component.inject(...) или прямой вызов метода-провайдера. Это оптимизирует стартовое время приложения.

  3. Не путать с аннотацией @javax.inject.Singleton: Dagger использует именно её. Важно импортировать правильную аннотацию:

    import javax.inject.Singleton
    
  4. Потокобезопасность: Dagger гарантирует потокобезопасное создание синглтонных зависимостей внутри компонента. Первый вызов в любом из потоков инициирует создание, последующие получат уже созданный экземпляр.

Итог: Время жизни зависимости с аннотацией @Singleton в Dagger равно времени жизни компонента, в модуле которого она объявлена. Для создания настоящего синглтона на всё приложение необходимо:

  • Пометить зависимость @Singleton.
  • Объявить её в модуле компонента, привязанного к Application (или другому контейнеру с жизненным циклом всего процесса).
  • Убедиться, что этот компонент создается в Application классе в единственном экземпляре и не пересоздается.
Как долго живет зависимость помеченная аннотацией Singleton в Dagger | PrepBro