Dagger / Hilt: mi ez, DI és alkalmazás

Szerző: IT Sectr Megjelenés: 2026-05-03 Olvasási idő: 9 perc

Dagger — egy függőséginjektálási keretrendszer Java-hoz és Kotlin-hoz, amely DI kódot generál fordítási időben annotációk feldolgozásával. Hilt — egy réteg a Dagger felett Android-hoz, amely leegyszerűsíti a komponensek és az életciklus konfigurálását. A Google, 2025 adatai szerint a Hilt a Google Play Top-100-ból több mint 70%-ában használatos, támogatva az Activity, Fragment, ViewModel és Service komponenseket előre meghatározott komponenseken keresztül. Mindkét keretrendszer biztosítja a függőségi gráf fordítási időben történő ellenőrzését, kiküszöbölve a futásidejű injektálási hibákat.

Főbb pontok

  • Dagger — fordítási idejű DI keretrendszer kódgenerálással @Module, @Provides, @Component annotációkon keresztül
  • Hilt — Android réteg, amely leegyszerűsíti a Dagger-t @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel segítségével
  • Component — függőségi gráf, amely a Module-t az Inject célokkal köti össze proxy metódusokon keresztül
  • Scope — @Singleton, @ViewModelScoped, @ActivityScoped kezelik az injektált objektumok élettartamát
  • Hilt támogatja a többmodulos projekteket @InstallIn segítségével elkülönített függőségi gráfokhoz

Mi az a Dagger / Hilt?

Dagger — egy függőséginjektálási keretrendszer kódgenerálással fordítási időben (compile-time DI). A Square-ben fejlesztették, majd később a Google-nak adták át, a Dagger a Java APT annotációs processzort használja a függőségi gráf elemzésére és gyári osztályok generálására. A runtime-DI-vel (Guice, Koin) ellentétben a Dagger nem használ reflexiót — minden kód fordítási időben készül, ami maximális teljesítményt biztosít futásidőben és hibafelismerést a build fázisban.

Hilt — egy Google könyvtár, amely a Dagger tetejére épül és Android-ra optimalizált. A Hilt előre meghatározott komponenseket biztosít, amelyek megfelelnek az Android komponensek életciklusának: @SingletonComponent az Application-hoz, @ActivityComponent az Activity-hez, @FragmentComponent a Fragment-hez, @ViewModelComponent a ViewModel-hez. Ez kiküszöböli a Component és Module rutinszerű konfigurálását, ami a tiszta Dagger-ben szükséges. A Hilt automatikusan generálja a függőségi gráfot minden Android komponenshez a @AndroidEntryPoint segítségével.

A Google I/O 2024 szerint a Hilt az ajánlott DI megoldás Kotlin-ban írt Android alkalmazásokhoz. A Jetpack könyvtárak (Navigation, Room, WorkManager) beépített integrációval rendelkeznek a Hilt-tel a @HiltViewModel és @HiltWorker segítségével. Azokban a projektekben, amelyek nem használnak Android-ot (tiszta Java/Kotlin könyvtárak, szerver alkalmazások), tiszta Dagger-t alkalmaznak Hilt réteg nélkül.

A kézi függőséginjektálás problémája

DI keretrendszer nélkül a fejlesztő manuálisan hozza létre az objektumokat konstruktorokon vagy gyárakon keresztül, láncban továbbadva a függőségeket. Minden új követelmény — az összes konstruktor aláírásának megváltoztatása a láncban. Dagger automatizálja ezt a folyamatot: elég deklarálni, hogy milyen típusra van szükség (@Inject constructor), és a Dagger létrehozza a függőségi gráfot, megoldva az összes beágyazott típust. A függőségek változásakor a Dagger automatikusan frissíti a generált kódot — lehetetlen hibázni a láncban.

A függőséginjektálás elvei

Függőséginjektálás (Dependency Injection) — egy minta, amelyben egy objektum kívülről kapja meg a függőségeit, ahelyett, hogy maga hozná létre azokat. A DI megvalósítja az inverzió vezérlés (IoC) elvét: az osztály nem felelős a saját függőségei létrehozásáért, hanem azokat konstruktoron, metóduson vagy mezőn keresztül deklarálja. A konstruktoron keresztüli injektálás (constructor injection) tekinthető a legkedveltebbnek, mert garantálja, hogy az objektum érvényes állapotban jön létre.

Injektálás típusaDagger szintaxisMikor használjuk
Constructor injection@Inject constructorFő módszer — minden saját osztályhoz
Field injection@Inject lateinit varCsak Android komponensekhez (Activity, Fragment)
Method injection@Inject fun bind()Post-construct inicializáláshoz

A compile-time DI előnyei

A DI fő előnyei közé tartozik a tesztelhetőség (a függőségek mock objektumokkal helyettesíthetők), laza csatolás (az osztályok interfészektől függnek, nem implementációktól), és az objektumok életciklusának explicit kezelése scope-okon keresztül. Dagger automatikusan garantálja, hogy egy objektum egyszer jön létre a saját scope-ján belül, és megsemmisül a scope elhagyásakor.

A Dagger architektúrája: Component, Module, Provides

Component — a Dagger függőségi gráf központi eleme. Ez egy @Component annotációval ellátott interfész, amely leírja a hidat a Module és az injektálási célok között. A Dagger generálja a Component implementációját (pl. DaggerAppComponent) fordítási időben. A Component meghatározza, mely típusok állnak rendelkezésre injektáláshoz, absztrakt metódusokon keresztül, amelyek visszaadják a szükséges típusokat, vagy inject metódusokon keresztül, amelyek egy objektumot fogadnak el field injection-hez.

kotlin
// Modul: olyan függőségeket biztosít, amelyeket a Dagger nem tud létrehozni
@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)
    }
}

// Komponens: összeköti a Module-t és az injektálási célokat
@Component(modules = [NetworkModule::class])
interface AppComponent {
    fun inject(activity: MainActivity)
    fun getApiService(): ApiService
}

@Module — egy osztály, amely @Provides metódusokat tartalmaz, amelyek függőségi példányokat adnak vissza. A Module olyan típusokhoz használatos, amelyeket a Dagger nem tud automatikusan létrehozni: harmadik féltől származó könyvtárak (OkHttp, Retrofit), konstruktor paraméterekkel rendelkező objektumok, implementációválasztással rendelkező interfészek. @Binds — alternatíva a @Provides számára olyan esetekben, amikor a metódus egy interfészt ad vissza és egyetlen implementációt fogad: a Dagger közvetlen cast-ot generál a metódus meghívása nélkül.

@Scope meghatározza az objektum élettartamát a függőségi gráfban. @Singleton — az objektum egyszer jön létre a teljes alkalmazáshoz. @ActivityScoped — az objektum addig él, amíg az Activity él. @FragmentScoped — amíg a Fragment él. Scope nélkül a Dagger minden injektáláskor új példányt hoz létre. @Reusable — olyan objektumok scope-ja, amelyeknek nem kell singleton-nak lenniük, de létrehozásuk költséges — a Dagger gyorsítótárazhatja a példányt, de nem garantálja ezt.

Hilt Android-hoz: @HiltAndroidApp és @AndroidEntryPoint

Hilt leegyszerűsíti a Dagger konfigurálását Android-hoz az előre meghatározott komponenseknek és az alapgráf automatikus generálásának köszönhetően. A @HiltAndroidApp annotáció az Application osztályon elindítja a Hilt komponens generálását. Ezen annotáció nélkül a Hilt nem működik — kötelező minden Hilt-et használó Android alkalmazáshoz. A @HiltAndroidApp létrehozza a szülő SingletonComponent komponenst, amelytől az alkalmazás összes többi komponense örököl.

kotlin
@HiltAndroidApp
class MyApplication : Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var apiService: ApiService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // az apiService már injektálva lett az onCreate hívása előtt
    }
}

@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 — annotáció Activity, Fragment, Service, BroadcastReceiver és View számára. Hilt komponenst generál minden típushoz: az Activity-n lévő @AndroidEntryPoint létrehozza az ActivityComponent-ot, amely a SingletonComponent-től örököl. A gyermek komponens automatikusan megkapja a szülő összes függőségét. A @Inject lateinit var field injection csak a @AndroidEntryPoint annotációval ellátott osztályokban érhető el — a hétköznapi osztályokban constructor injection használatos.

@InstallIn jelzi, hogy a modul melyik Hilt komponensbe kerül telepítésre. A @InstallIn(SingletonComponent::class) NetworkModule a teljes alkalmazásban elérhető. A @InstallIn(ActivityComponent::class) Module — csak Activity-ben. Ez elkülöníti a függőségi gráfokat: az Activity-specifikus modulok nem láthatók a Fragment-ben és ViewModel-ben, megakadályozva a nem engedélyezett függőségek véletlen használatát. @ApplicationContext — a Hilt beépített minősítője az alkalmazás kontextusának lekéréséhez.

Qualifier: @Named és egyéni minősítők

Amikor ugyanazon interfész két különböző implementációját kell injektálni, minősítőket használunk. A Hilt támogatja a @Named annotációt szöveges azonosítókhoz és egyéni annotációkat a @Qualifier-rel. Például @Named("baseUrl") és @Named("imageBaseUrl") különböző szöveges konfigurációkhoz. Az egyéni minősítők előnyösebbek a @Named-nél a fordítási időben történő ellenőrzés miatt — a helytelen szöveges név csak futásidőben derül ki.

Hilt ViewModel: @HiltViewModel és @Inject constructor

@HiltViewModel — annotáció, amely helyettesíti a kézi ViewModelProvider.Factory gyárat. A @HiltViewModel annotációval és @Inject constructor-ral ellátott osztály automatikusan megkapja az összes függőséget a Dagger-en keresztül. A Hilt generálja a ViewModelFactory-t, amelyet a Jetpack ViewModelProvider használ. Hilt nélkül a fejlesztőnek kézzel kellene megírnia a gyárat, minden paramétert az Activity-ből vagy fragment-ből átadva.

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-ben — a Hilt automatikusan létrehozza a ViewModel-t
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()
}

ViewModelScoped — Hilt scope olyan függőségekhez, amelyek addig élnek, amíg a ViewModel él. Ha két azonos típusú ViewModel ugyanazt a @ViewModelScoped függőséget injektálja, mindegyik saját példányt kap. Ez különbözteti meg a @ViewModelScoped-ot a @ActivityScoped-tól, ahol egy Activity egy példányt kap az összes fragment számára. ViewMmodell-specifikus függőségekhez (pl. SavedStateHandle) használja a @HiltViewModel-t @Inject constructor(savedStateHandle: SavedStateHandle) formában.

A Hilt támogatja az assisted injection-t a Hilt Extensions könyvtáron keresztül. Az assisted injection lehetővé teszi paraméterek átadását a konstruktornak injektálás közben, amikor a függőségek egy része csak futásidőben ismert (pl. felhasználói ID intent-ből). Az assisted injection-hez a @AssistedInject használandó @Assisted paraméterekkel kombinálva. A Hilt generálja az AssistedFactory-t, amely szabványos módon injektálható.

Dagger vs Hilt: összehasonlítás és migráció

Tiszta Dagger a Component kézi létrehozását, scope-ok meghatározását és az injektálás konfigurálását igényli minden Android komponensben. A fejlesztő létrehozza az AppComponent, ActivityComponent, FragmentComponent komponenseket, és @Subcomponent segítségével kezeli kapcsolataikat. Ez a megközelítés maximális kontrollt biztosít, de jelentős mennyiségű boilerplate kódot igényel. A Dagger nagy projektekben használatos, ahol egyedi DI architektúra szükséges, vagy nem Android Java/Kotlin projektekben.

Hilt automatizálja a boilerplate-ot: egy @HiltAndroidApp, egy @AndroidEntryPoint minden komponenshez, előre meghatározott scope-ok. A Hilt-et a Google ajánlja minden új Android projekthez. A Dagger-ről Hilt-re migrálás magában foglalja a Component @InstallIn-nel való helyettesítését, a @Subcomponent előre meghatározott Hilt komponensekkel való helyettesítését és a kézi ViewModelProvider.Factory @HiltViewModel-lel való helyettesítését. A legtöbb @Module osztály a @Provides metódusok módosítása nélkül kerül átvitelre a @InstallIn hozzáadásával.

JellemzőDaggerHilt
KonfigurációKézi: Component, Subcomponent, BuilderAutomatikus: @HiltAndroidApp, @AndroidEntryPoint
Android komponensekNincsenek előre meghatározva12+ beépített komponens
ViewModelKézi gyár@HiltViewModel + @Inject constructor
Többmodul@Component(dependencies) segítségével@InstallIn + aggregáció segítségével
BonyolultságMagas — tapasztalat szükségesAlacsony — intuitív
RugalmasságMaximálisSzabványos (a forgatókönyvek 95%-át lefedi)

A Hilt korlátai: a könyvtár csak Android-ot támogat (nem alkalmas tiszta szerver Java projektekhez), meghatározott komponensstruktúrát kényszerít ki (nehéz felülírni), és függőséget ad hozzá az android.hilt:hilt-navigation-compose-hoz Jetpack Compose projektekhez. Compose alkalmazásokhoz a Hilt @HiltViewModel-t biztosít, amely elérhető a Composable-ben a hiltViewModel() segítségével — anélkül, hogy manuálisan kellene biztosítani a ViewModel-t az Activity-ből.

Gyakran ismételt kérdések

Mi a különbség a Dagger és a Hilt között?

Dagger — alap compile-time DI keretrendszer a Component és Module kézi konfigurálásával. Hilt — Android réteg, amely automatizálja a komponensek létrehozását és integrációját az Activity, Fragment, ViewModel, Service és BroadcastReceiver életciklusával.

Mire való a @HiltAndroidApp?

@HiltAndroidApp bekapcsolja a Hilt komponens generálását az Application számára. Ezen annotáció nélkül a Hilt nem tudja létrehozni az alap SingletonComponent komponenst, amelytől az összes ActivityComponent, FragmentComponent és ViewModelComponent örököl. Az annotáció minden Hilt projekthez kötelező.

Hogyan működik a Hilt a Jetpack Navigation-nel?

Hilt Navigation @HiltViewModel-t biztosít a ViewModel számára NavBackStackEntry-ben és hiltNavGraphViewModels()-t a ViewModel scope-olásához a navigációs gráfon belül. Az android.hilt:hilt-navigation-fragment könyvtár automatikusan létrehozza a ViewModel-t minden NavBackStackEntry-hez.

Hogyan lehet Context-et injektálni a Hilt-ben?

Használja a @ApplicationContext-et az alkalmazás kontextusához vagy a @ActivityContext-et az Activity kontextusához. A Hilt ezeket a minősítőket beépítve biztosítja az android.hilt:hilt-android könyvtárban. A @ActivityContext csak az ActivityComponent-be telepített modulokban érhető el.

Mi az a @Binds és mikor használjuk?

@Binds — hatékony alternatíva a @Provides számára, amikor a metódus pontosan egy paramétert fogad és visszaadja annak típusát interfészként. A @Binds közvetlen cast-ot generál a metódus meghívása nélkül, ami csökkenti a generált kód mennyiségét és növeli a teljesítményt injektáláskor.

Összefoglalás

  • Dagger — compile-time DI keretrendszer @Module, @Provides, @Component annotációkkal és APT-n keresztüli kódgenerálással
  • Hilt — Android réteg a Dagger felett @HiltAndroidApp, @AndroidEntryPoint, @InstallIn és előre meghatározott komponensekkel
  • Component kezeli a függőségi gráfot, Module biztosítja a harmadik féltől származó osztályokat, Provides — objektumgyárakat
  • Scope (@Singleton, @ViewModelScoped, @ActivityScoped) meghatározza az objektum élettartamát a Dagger gráfban
  • @HiltViewModel automatizálja a ViewModel létrehozását, kiküszöbölve a kézi ViewModelProvider.Factory gyárakat
  • @InstallIn elkülöníti a modulokat komponensek szerint, megakadályozva a függőségek szivárgását az alkalmazásrétegek között
  • Hilt a Google ajánlása minden új Android projekthez, a Dagger — nem Android és egyedi DI architektúrákhoz

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is