Dagger / Hilt: шта је то, DI и примена

Аутор: IT Sectr Објављено: 2026-05-03 Време читања: 9 мин

Dagger — јесте фрејмворк за убризгавање зависности за Java и Kotlin, који генерише DI код у фази компилације кроз обраду анотација. Hilt — јесте надградња над Dagger-ом за Android, која поједностављује подешавање компонената и животног циклуса. Према подацима Google, 2025, Hilt се користи у више од 70% Android апликација из Google Play Top-100, подржавајући Activity, Fragment, ViewModel и Service кроз предефинисане компоненте. Оба фрејмворка обезбеђују проверу графа зависности у време компилације, елиминишући грешке убризгавања у време извршавања.

Главне карактеристике

  • Dagger — DI фрејмворк за време компилације са генерисањем кода кроз анотације @Module, @Provides, @Component
  • Hilt — надградња за Android која поједностављује Dagger кроз @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel
  • Component — граф зависности који повезује Module са Inject циљевима кроз прокси методе
  • Scope — @Singleton, @ViewModelScoped, @ActivityScoped управљају животним веком убризганих објеката
  • Hilt подржава вишемодулне пројекте кроз @InstallIn за изоловане графове зависности

Шта је Dagger / Hilt?

Dagger — јесте фрејмворк за убризгавање зависности са генерисањем кода у фази компилације (compile-time DI). Развијен у Square-у и касније предат Google-у, Dagger користи процесор анотација Java APT за анализу графа зависности и генерисање фабричких класа. За разлику од runtime-DI (Guice, Koin), Dagger не користи рефлексију — сав код се ствара при компилацији, што обезбеђује максималне перформансе у рантиме-у и откривање грешака у фази изградње.

Hilt — јесте библиотека од Google-а, изграђена на Dagger-у и оптимизована за Android. Hilt пружа предефинисане компоненте које одговарају животном циклусу Android компонената: @SingletonComponent за Application, @ActivityComponent за Activity, @FragmentComponent за Fragment, @ViewModelComponent за ViewModel. Ово елиминише рутинско подешавање Component и Module које је потребно у чистом Dagger-у. Hilt такође генерише граф зависности за сваку Android компоненту аутоматски кроз @AndroidEntryPoint.

Према Google I/O 2024, Hilt је препоручено решење за DI у Android апликацијама писаним у Kotlin-у. Jetpack библиотеке (Navigation, Room, WorkManager) имају уграђену интеграцију са Hilt-ом кроз @HiltViewModel и @HiltWorker. У пројектима који не користе Android (чисте Java/Kotlin библиотеке, серверске апликације), примењује се чист Dagger без Hilt надградње.

Проблем ручног убризгавања зависности

Без DI фрејмворка, програмер креира објекте ручно кроз конструкторе или фабрике, преносећи зависности дуж ланца. Сваки нови захтев — промена сигнатуре свих конструктора у ланцу. Dagger аутоматизује овај процес: довољно је декларисати који тип је потребан (@Inject constructor), и Dagger ће креирати граф зависности, решавајући све угнежђене типове. При промени зависности, Dagger аутоматски ажурира генерисани код — немогуће је погрешити у ланцу.

Принципи убризгавања зависности

Убризгавање зависности (Dependency Injection) — јесте образац у којем објекат прима своје зависности споља, а не ствара их сам. DI имплементира принцип инверзије контроле (IoC): класа није одговорна за стварање својих зависности, већ их декларише кроз конструктор, метод или поље. Убризгавање кроз конструктор (constructor injection) сматра се најпожељнијим, јер гарантује да се објекат креира у валидном стању.

Тип убризгавањаСинтакса Dagger-аКада користити
Constructor injection@Inject constructorГлавни начин — за све сопствене класе
Field injection@Inject lateinit varСамо за Android компоненте (Activity, Fragment)
Method injection@Inject fun bind()За пост-конструкт иницијализацију

Предности compile-time DI

Главне предности DI укључују тестирабилност (зависности се могу заменити mock објектима), слабу повезаност (класе зависе од интерфејса, а не имплементација) и експлицитно управљање животним циклусом објеката кроз scope-ове. Dagger аутоматски гарантује да се објекат креира једном у оквиру свог scope-а и уништава при изласку из scope-а.

Архитектура Dagger-а: Component, Module, Provides

Component — централни елемент графа зависности Dagger-а. То је интерфејс анотиран са @Component који описује мост између Module-а и циљева убризгавања. Dagger генерише имплементацију Component (нпр. DaggerAppComponent) у фази компилације. Component одређује који типови су доступни за убризгавање, кроз апстрактне методе које враћају потребне типове или кроз inject методе које примају објекат за field injection.

kotlin
// Модул: обезбеђује зависности које Dagger не може сам креирати
@Module
class NetworkModule {
    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .build()
    }

    @Provides
    @Singleton
    fun provideApiService(client: OkHttpClient): ApiService {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
}

// Компонента: повезује Module и циљеве убризгавања
@Component(modules = [NetworkModule::class])
interface AppComponent {
    fun inject(activity: MainActivity)
    fun getApiService(): ApiService
}

@Module — јесте класа која садржи методе са @Provides које враћају инстанце зависности. Module се користи за типове које Dagger не може аутоматски креирати: библиотеке трећих страна (OkHttp, Retrofit), објекти са параметрима конструктора, интерфејси са избором имплементације. @Binds — алтернатива за @Provides у случајевима када метод враћа интерфејс и прима једну имплементацију: Dagger генерише директан cast без позивања метода.

@Scope одређује животни век објекта у графу зависности. @Singleton — објекат се креира једном за целу апликацију. @ActivityScoped — објекат живи док живи Activity. @FragmentScoped — док живи Fragment. Без scope-а, Dagger креира нову инстанцу при сваком убризгавању. @Reusable — scope за објекте који не морају бити синглтони, али је њихово креирање скупо — Dagger може кеширати инстанцу, али то не гарантује.

Hilt за Android: @HiltAndroidApp и @AndroidEntryPoint

Hilt поједностављује подешавање Dagger-а за Android захваљујући предефинисаним компонентама и аутоматском генерисању основног графа. Анотација @HiltAndroidApp на Application класи покреће генерисање Hilt компоненте. Без ове анотације Hilt не ради — обавезна је за сваку Android апликацију која користи Hilt. @HiltAndroidApp креира родитељску компоненту SingletonComponent, од које наслеђују све остале компоненте апликације.

kotlin
@HiltAndroidApp
class MyApplication : Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var apiService: ApiService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // apiService је већ убризган пре позива onCreate
    }
}

@Module
@InstallIn(SingletonComponent::class)
class AppModule {
    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext ctx: Context): AppDatabase {
        return Room.databaseBuilder(ctx, AppDatabase::class.java, "app.db").build()
    }
}

@AndroidEntryPoint — анотација за Activity, Fragment, Service, BroadcastReceiver и View. Генерише Hilt компоненту за сваки тип: @AndroidEntryPoint на Activity креира ActivityComponent, који наслеђује од SingletonComponent. Дете компонента аутоматски прима све зависности родитеља. Field injection са @Inject lateinit var доступан је само у класама анотираним са @AndroidEntryPoint — у обичним класама користи се constructor injection.

@InstallIn указује у коју Hilt компоненту се инсталира модул. NetworkModule са @InstallIn(SingletonComponent::class) доступан је у целој апликацији. Module са @InstallIn(ActivityComponent::class) — само у Activity. Ово изолује графове зависности: модули специфични за Activity нису видљиви у Fragment и ViewModel, спречавајући случајно коришћење недозвољених зависности. @ApplicationContext — уграђени квалификатор Hilt-а за добијање контекста апликације.

Qualifier: @Named и прилагођени квалификатори

Када је потребно убризгати две различите имплементације истог интерфејса, користе се квалификатори. Hilt подржава @Named за текстуалне идентификаторе и прилагођене анотације са @Qualifier. На пример, @Named("baseUrl") и @Named("imageBaseUrl") за различите текстуалне конфигурације. Прилагођени квалификатори су пожељнији од @Named због провере у фази компилације — нетачно име текста неће бити откривено до рантиме-а.

Hilt ViewModel: @HiltViewModel и @Inject constructor

@HiltViewModel — анотација која замењује ручну фабрику ViewModelProvider.Factory. Класа анотирана са @HiltViewModel са @Inject constructor аутоматски прима све зависности кроз Dagger. Hilt генерише ViewModelFactory коју користи Jetpack ViewModelProvider. Без Hilt-а, програмер би морао да пише фабрику ручно, преносећи сваки параметар из Activity или фрагмента.

kotlin
@HiltViewModel
class MainViewModel
    @Inject constructor(
        private val apiService: ApiService,
        private val database: AppDatabase
    ) : ViewModel() {

    private val _users = MutableStateFlow<List<User>>(emptyList())
    val users: StateFlow<List<User>> = _users.asStateFlow()

    fun loadUsers() {
        viewModelScope.launch {
            _users.value = apiService.getUsers()
        }
    }
}

// У Activity — Hilt аутоматски креира ViewModel
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
}

ViewModelScoped — Hilt scope за зависности које живе док живи ViewModel. Ако два ViewModel истог типа убризгавају исту @ViewModelScoped зависност, сваки добија своју инстанцу. Ово разликује @ViewModelScoped од @ActivityScoped, где једно Activity добија једну инстанцу за све фрагменте. За ViewModel-специфичне зависности (нпр. SavedStateHandle) користи се @HiltViewModel са @Inject constructor(savedStateHandle: SavedStateHandle).

Hilt подржава assisted injection кроз библиотеку Hilt Extensions. Assisted injection омогућава прослеђивање параметара конструктору током убризгавања, када је део зависности познат само у рантиме-у (нпр. ID корисника из intent-а). За assisted injection користи се @AssistedInject у комбинацији са @Assisted параметрима. Hilt генерише AssistedFactory, која се може убризгати на стандардан начин.

Dagger vs Hilt: поређење и миграција

Чисти Dagger захтева ручно креирање Component, дефинисање scope-ова и подешавање убризгавања у свакој Android компоненти. Програмер креира AppComponent, ActivityComponent, FragmentComponent, управља њиховим везама кроз @Subcomponent. Овај приступ пружа максималну контролу, али захтева значајну количину boilerplate кода. Dagger се користи у великим пројектима где је потребна прилагођена DI архитектура или у не-Android Java/Kotlin пројектима.

Hilt аутоматизује boilerplate: један @HiltAndroidApp, један @AndroidEntryPoint за сваку компоненту, предефинисани scope-ови. Hilt препоручује Google за све нове Android пројекте. Миграција са Dagger-а на Hilt укључује замену Component са @InstallIn, замену @Subcomponent са предефинисаним Hilt компонентама и замену ручног ViewModelProvider.Factory са @HiltViewModel. Већина @Module класа се преноси са додавањем @InstallIn без измене @Provides метода.

КарактеристикаDaggerHilt
ПодешавањеРучно: Component, Subcomponent, BuilderАуто: @HiltAndroidApp, @AndroidEntryPoint
Android компонентеНема предефинисаних12+ уграђених компонената
ViewModelРучна фабрика@HiltViewModel + @Inject constructor
МултимодулКроз @Component(dependencies)Кроз @InstallIn + агрегацију
СложеностВисока — потребно искуствоНиска — интуитивна
ФлексибилностМаксималнаСтандардна (покрива 95% сценарија)

Ограничења Hilt-а: библиотека подржава само Android (није погодна за чисто серверске Java пројекте), намеће одређену структуру компонената (тешко је превазићи) и додаје зависност од android.hilt:hilt-navigation-compose за Jetpack Compose пројекте. За Compose апликације, Hilt пружа @HiltViewModel доступан у Composable-у кроз hiltViewModel() — без ручног обезбеђивања ViewModel из Activity.

Често постављана питања

Која је разлика између Dagger-а и Hilt-а?

Dagger — основни DI фрејмворк за време компилације са ручним подешавањем Component и Module. Hilt — надградња за Android која аутоматизује креирање компонената и интеграцију са животним циклусом Activity, Fragment, ViewModel, Service и BroadcastReceiver-а.

Чему служи @HiltAndroidApp?

@HiltAndroidApp укључује генерисање Hilt компоненте за Application. Без ове анотације Hilt не може креирати основну компоненту SingletonComponent, од које наслеђују сви ActivityComponent, FragmentComponent и ViewModelComponent. Анотација је обавезна за сваки Hilt пројекат.

Како Hilt ради са Jetpack Navigation?

Hilt Navigation пружа @HiltViewModel за ViewModel у NavBackStackEntry и hiltNavGraphViewModels() за скоуповање ViewModel у оквиру навигационог графа. Библиотека android.hilt:hilt-navigation-fragment аутоматски креира ViewModel за сваки NavBackStackEntry.

Како убризгати Context у Hilt?

Користите @ApplicationContext за контекст апликације или @ActivityContext за контекст Activity. Hilt пружа ове квалификаторе уграђене у библиотеку android.hilt:hilt-android. @ActivityContext је доступан само у модулима инсталираним у ActivityComponent.

Шта је @Binds и када се користи?

@Binds — ефикасна алтернатива за @Provides, када метод прима тачно један параметар и враћа његов тип као интерфејс. @Binds генерише директан cast без позивања метода, што смањује количину генерисаног кода и повећава перформансе при убризгавању.

Резиме

  • Dagger — DI фрејмворк за време компилације са анотацијама @Module, @Provides, @Component и генерисањем кода кроз APT
  • Hilt — Android надградња над Dagger-ом са @HiltAndroidApp, @AndroidEntryPoint, @InstallIn и предефинисаним компонентама
  • Component управља графом зависности, Module обезбеђује класе трећих страна, Provides — фабрике објеката
  • Scope (@Singleton, @ViewModelScoped, @ActivityScoped) одређује животни век објекта у Dagger графу
  • @HiltViewModel аутоматизује креирање ViewModel, елиминишући ручне фабрике ViewModelProvider.Factory
  • @InstallIn изолује модуле по компонентама, спречавајући цурење зависности између слојева апликације
  • Hilt препоручује Google за све нове Android пројекте, Dagger — за не-Android и прилагођене DI архитектуре

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође