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

Сколько раз создается Dagger Lazy?

1.2 Junior🔥 71 комментариев
#Dependency Injection

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

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

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

Ответ на вопрос о количестве созданий Dagger Lazy

Что такое Lazy<T> в Dagger?

В Dagger Lazy<T> — это специальный тип поставщика (provider), который позволяет отложить инициализацию зависимости до первого реального использования. Это достигается за счёт ленивой инициализации (lazy initialization). Ключевой момент: Lazy<T> не создаёт сам инстанс зависимости сразу, а лишь оборачивает её в прокси-объект, который при первом вызове метода .get() делегирует создание реального объекту Dagger'у. После первого создания инстанс кэшируется на уровне этого конкретного объекта Lazy.

Сколько раз создаётся Lazy<T>?

Ответ зависит от контекста, но в типичном сценарии:

  1. Lazy-обёртка создаётся один раз при внедрении (injection). Например:
class MyViewModel @Inject constructor(
    private val serviceLazy: Lazy<MyService>
) {
    fun doWork() {
        val service = serviceLazy.get() // Создание MyService происходит здесь
    }
}

Здесь объект Lazy<MyService> создаётся Dagger'ом один раз при создании MyViewModel.

  1. Реальная зависимость (MyService) создаётся также один раз, но только при первом вызове .get(). Например:
fun example() {
    val service1 = serviceLazy.get() // MyService создаётся здесь
    val service2 = serviceLazy.get() // Возвращается уже созданный экземпляр из кэша
    // service1 === service2 возвращает true
}

Важные нюансы и исключения

1. Влияние скоупов (Scopes)

  • Если MyService не имеет скоупа (@Singleton, @ActivityScope и т.д.), то каждый новый Lazy<MyService> будет создавать новый экземпляр MyService при вызове .get().
  • Если MyService имеет скоуп (например, @Singleton), то даже при использовании в разных Lazy объектах, Dagger обеспечит единственный экземпляр на весь скоуп.

2. Сценарий с множественными внедрениями

class Example @Inject constructor(
    private val lazy1: Lazy<MyService>,
    private val lazy2: Lazy<MyService>
) {
    fun test() {
        val a = lazy1.get() // Создаётся MyService, если ранее не создан
        val b = lazy2.get() // Возвращается тот же объект, что и для lazy1 (если MyService в синглтоне)
        // Если MyService без скоупа, lazy1.get() и lazy2.get() создадут РАЗНЫЕ объекты
    }
}

Здесь создаются два разных объекта Lazy<MyService>, но реальный MyService может быть одним или двумя экземплярами в зависимости от его скоупа.

3. Provider<T> vs Lazy<T>

Для сравнения:

  • Provider<T> создаётся один раз, но каждый вызов .get() возвращает новый инстанс (или синглтон, если зависимость в скоупе).
  • Lazy<T> создаётся один раз, но хранит кэшированный инстанс после первого .get().

Практический пример

Рассмотрим конфигурацию:

@Module
class AppModule {
    @Provides
    @Singleton
    fun provideMyService(): MyService = MyService()
}

@Component(modules = [AppModule::class])
@Singleton
interface AppComponent {
    fun inject(activity: MainActivity)
}

class MainActivity : AppCompatActivity() {
    @Inject lateinit var lazyService: Lazy<MyService>
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        component.inject(this)
        
        // Lazy объект уже создан Dagger'ом, но MyService ещё нет
        val service1 = lazyService.get() // MyService создаётся здесь
        val service2 = lazyService.get() // Используется существующий экземпляр
    }
}

Выводы

  • Объект Lazy<T> создаётся ровно один раз для каждого места внедрения (injection site).
  • Зависимость T внутри Lazy создаётся при первом вызове .get() и также один раз для данного конкретного объекта Lazy (если зависимость не имеет скоупа, то для каждого Lazy будет свой экземпляр).
  • Количество реальных созданий объекта T зависит от скоупа и количества различных объектов Lazy<T>, в которые он внедрён.

Таким образом, типичный ответ: Dagger Lazy создаётся один раз на инъекцию, но реальная зависимость внутри него создаётся лениво при первом обращении. Это делает Lazy полезным инструментом для оптимизации производительности, особенно при работе с тяжёлыми в инициализации зависимостями.