Dagger — je framework pro vkládání závislostí pro Javu a Kotlin, který generuje DI kód v době kompilace prostřednictvím zpracování anotací. Hilt — je nadstavba nad Daggerem pro Android, která zjednodušuje konfiguraci komponent a životního cyklu. Podle údajů Google, 2025 je Hilt používán ve více než 70% Android aplikací z Google Play Top-100, podporuje Activity, Fragment, ViewModel a Service prostřednictvím předdefinovaných komponent. Oba frameworky zajišťují kontrolu grafu závislostí v době kompilace, čímž eliminují chyby vkládání za běhu.
Hlavní body
Dagger — je framework pro vkládání závislostí s generováním kódu v době kompilace (compile-time DI). Vyvinutý ve Square a později předaný Google, Dagger používá procesor anotací Java APT k analýze grafu závislostí a generování továrních tříd. Na rozdíl od runtime-DI (Guice, Koin) Dagger nepoužívá reflexi — veškerý kód je vytvořen při kompilaci, což zajišťuje maximální výkon za běhu a odhalování chyb ve fázi sestavení.
Hilt — je knihovna od Google, postavená na Daggeru a optimalizovaná pro Android. Hilt poskytuje předdefinované komponenty odpovídající životnímu cyklu Android komponent: @SingletonComponent pro Application, @ActivityComponent pro Activity, @FragmentComponent pro Fragment, @ViewModelComponent pro ViewModel. To eliminuje rutinní konfiguraci Component a Module, která je vyžadována v čistém Daggeru. Hilt také automaticky generuje graf závislostí pro každou Android komponentu prostřednictvím @AndroidEntryPoint.
Podle Google I/O 2024 je Hilt doporučeným řešením DI pro Android aplikace napsané v Kotlinu. Knihovny Jetpack (Navigation, Room, WorkManager) mají vestavěnou integraci s Hiltem přes @HiltViewModel a @HiltWorker. V projektech, které nepoužívají Android (čisté Java/Kotlin knihovny, serverové aplikace), se používá čistý Dagger bez nadstavby Hilt.
Bez DI frameworku vývojář vytváří objekty ručně pomocí konstruktorů nebo továren, přičemž předává závislosti v řetězci. Každý nový požadavek — změna signatury všech konstruktorů v řetězci. Dagger tento proces automatizuje: stačí deklarovat, jaký typ je požadován (@Inject constructor), a Dagger vytvoří graf závislostí, vyřeší všechny vnořené typy. Při změně závislostí Dagger automaticky aktualizuje generovaný kód — v řetězci nelze udělat chybu.
Vkládání závislostí (Dependency Injection) — je vzor, při kterém objekt přijímá své závislosti z venku, místo aby je sám vytvářel. DI implementuje princip inverze řízení (IoC): třída není odpovědná za vytváření svých závislostí, ale deklaruje je prostřednictvím konstruktoru, metody nebo pole. Vkládání přes konstruktor (constructor injection) je považováno za nejpreferovanější, protože zaručuje, že objekt je vytvořen v platném stavu.
| Typ vkládání | Syntaxe Daggeru | Kdy použít |
|---|---|---|
| Constructor injection | @Inject constructor | Hlavní způsob — pro všechny vlastní třídy |
| Field injection | @Inject lateinit var | Pouze pro Android komponenty (Activity, Fragment) |
| Method injection | @Inject fun bind() | Pro post-construct inicializaci |
Hlavní výhody DI zahrnují testovatelnost (závislosti lze nahradit mock objekty), volnou provázanost (třídy závisí na rozhraních, ne na implementacích) a explicitní správu životního cyklu objektů pomocí scope. Dagger automaticky zaručuje, že objekt je vytvořen jednou v rámci svého scopu a zničen při opuštění scopu.
Component — centrální prvek grafu závislostí Daggeru. Je to rozhraní anotované @Component, které popisuje most mezi Modulem a cíli vkládání. Dagger generuje implementaci Component (např. DaggerAppComponent) v době kompilace. Component určuje, které typy jsou k dispozici pro vkládání, prostřednictvím abstraktních metod vracejících požadované typy nebo metod inject přijímajících objekt pro field injection.
// Modul: poskytuje závislosti, které Dagger nemůže vytvořit sám
@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)
}
}
// Komponenta: propojuje Module a cíle vkládání
@Component(modules = [NetworkModule::class])
interface AppComponent {
fun inject(activity: MainActivity)
fun getApiService(): ApiService
}
@Module — je třída obsahující metody s @Provides, které vracejí instance závislostí. Module se používá pro typy, které Dagger nemůže vytvořit automaticky: knihovny třetích stran (OkHttp, Retrofit), objekty s parametry konstruktoru, rozhraní s výběrem implementace. @Binds — alternativa k @Provides pro případy, kdy metoda vrací rozhraní a přijímá jedinou implementaci: Dagger generuje přímý přetypování bez volání metody.
@Scope určuje životnost objektu v grafu závislostí. @Singleton — objekt je vytvořen jednou pro celou aplikaci. @ActivityScoped — objekt žije, dokud žije Activity. @FragmentScoped — dokud žije Fragment. Bez scopu Dagger vytváří novou instanci při každém vkládání. @Reusable — scope pro objekty, které nemusí být singly, ale jejich vytvoření je nákladné — Dagger může instanci ukládat do mezipaměti, ale nezaručuje to.
Hilt zjednodušuje konfiguraci Daggeru pro Android díky předdefinovaným komponentám a automatickému generování základního grafu. Anotace @HiltAndroidApp na třídě Application spouští generování Hilt komponenty. Bez této anotace Hilt nefunguje — je povinná pro každou Android aplikaci používající Hilt. @HiltAndroidApp vytváří rodičovskou komponentu SingletonComponent, od které dědí všechny ostatní komponenty aplikace.
@HiltAndroidApp
class MyApplication : Application()
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var apiService: ApiService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// apiService byl již vložen před voláním 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 — anotace pro Activity, Fragment, Service, BroadcastReceiver a View. Generuje Hilt komponentu pro každý typ: @AndroidEntryPoint na Activity vytváří ActivityComponent, který dědí z SingletonComponent. Dceřiná komponenta automaticky přijímá všechny závislosti rodiče. Field injection s @Inject lateinit var je k dispozici pouze ve třídách anotovaných @AndroidEntryPoint — v běžných třídách se používá constructor injection.
@InstallIn určuje, do které Hilt komponenty je modul nainstalován. NetworkModule s @InstallIn(SingletonComponent::class) je k dispozici v celé aplikaci. Module s @InstallIn(ActivityComponent::class) — pouze v Activity. To izoluje grafy závislostí: moduly specifické pro Activity nejsou viditelné ve Fragment a ViewModel, čímž se zabraňuje náhodnému použití nepovolených závislostí. @ApplicationContext — vestavěný kvalifikátor Hiltu pro získání kontextu aplikace.
Když je třeba vložit dvě různé implementace stejného rozhraní, používají se kvalifikátory. Hilt podporuje @Named pro textové identifikátory a vlastní anotace s @Qualifier. Například @Named("baseUrl") a @Named("imageBaseUrl") pro různé textové konfigurace. Vlastní kvalifikátory jsou preferovány před @Named kvůli kontrole v době kompilace — nesprávný textový název nebude odhalen až do běhu.
@HiltViewModel — anotace nahrazující ruční továrnu ViewModelProvider.Factory. Třída anotovaná @HiltViewModel s @Inject constructor automaticky přijímá všechny závislosti přes Dagger. Hilt generuje ViewModelFactory používanou Jetpack ViewModelProvider. Bez Hiltu by vývojář musel psát továrnu ručně a předávat každý parametr z Activity nebo fragmentu.
@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()
}
}
}
// V Activity — Hilt automaticky vytváří ViewModel
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
}
ViewModelScoped — scope Hiltu pro závislosti, které žijí, dokud žije ViewModel. Pokud dva ViewModel stejného typu vkládají stejnou závislost @ViewModelScoped, každý dostane svou vlastní instanci. To odlišuje @ViewModelScoped od @ActivityScoped, kde jedna Activity dostává jednu instanci pro všechny fragmenty. Pro závislosti specifické pro ViewModel (např. SavedStateHandle) použijte @HiltViewModel s @Inject constructor(savedStateHandle: SavedStateHandle).
Hilt podporuje assisted injection prostřednictvím knihovny Hilt Extensions. Assisted injection umožňuje předávat parametry konstruktoru během vkládání, když je část závislostí známa pouze za běhu (např. ID uživatele z intentu). Pro assisted injection se používá @AssistedInject v kombinaci s parametry @Assisted. Hilt generuje AssistedFactory, kterou lze vložit standardním způsobem.
Čistý Dagger vyžaduje ruční vytvoření Component, definování scopů a konfiguraci vkládání v každé Android komponentě. Vývojář vytváří AppComponent, ActivityComponent, FragmentComponent a spravuje jejich vztahy prostřednictvím @Subcomponent. Tento přístup poskytuje maximální kontrolu, ale vyžaduje značné množství boilerplate kódu. Dagger se používá ve velkých projektech, kde je vyžadována vlastní DI architektura, nebo v ne-Android Java/Kotlin projektech.
Hilt automatizuje boilerplate: jeden @HiltAndroidApp, jeden @AndroidEntryPoint pro každou komponentu, předdefinované scopy. Hilt je doporučován Googlem pro všechny nové Android projekty. Migrace z Daggeru na Hilt zahrnuje nahrazení Component za @InstallIn, nahrazení @Subcomponent za předdefinované Hilt komponenty a nahrazení ručního ViewModelProvider.Factory za @HiltViewModel. Většina tříd @Module se přenáší s přidáním @InstallIn beze změny metod @Provides.
| Vlastnost | Dagger | Hilt |
|---|---|---|
| Konfigurace | Ruční: Component, Subcomponent, Builder | Automatická: @HiltAndroidApp, @AndroidEntryPoint |
| Android komponenty | Žádné předdefinované | 12+ vestavěných komponent |
| ViewModel | Ruční továrna | @HiltViewModel + @Inject constructor |
| Multimodul | Přes @Component(dependencies) | Přes @InstallIn + agregaci |
| Složitost | Vysoká — vyžaduje zkušenosti | Nízká — intuitivní |
| Flexibilita | Maximální | Standardní (pokrývá 95% scénářů) |
Omezení Hiltu: knihovna podporuje pouze Android (není vhodná pro čistě serverové Java projekty), vynucuje určitou strukturu komponent (obtížně přepisovatelnou) a přidává závislost na android.hilt:hilt-navigation-compose pro Jetpack Compose projekty. Pro Compose aplikace Hilt poskytuje @HiltViewModel dostupný v Composable přes hiltViewModel() — bez ručního poskytování ViewModel z Activity.
Často kladené otázky
Dagger — základní compile-time DI framework s ruční konfigurací Component a Module. Hilt — nadstavba pro Android automatizující vytváření komponent a integraci s životním cyklem Activity, Fragment, ViewModel, Service a BroadcastReceiver.
@HiltAndroidApp spouští generování Hilt komponenty pro Application. Bez této anotace Hilt nemůže vytvořit základní komponentu SingletonComponent, od které dědí všechny ActivityComponent, FragmentComponent a ViewModelComponent. Anotace je povinná pro každý Hilt projekt.
Hilt Navigation poskytuje @HiltViewModel pro ViewModel v NavBackStackEntry a hiltNavGraphViewModels() pro scopování ViewModel v rámci navigačního grafu. Knihovna android.hilt:hilt-navigation-fragment automaticky vytváří ViewModel pro každý NavBackStackEntry.
Použijte @ApplicationContext pro kontext aplikace nebo @ActivityContext pro kontext Activity. Hilt poskytuje tyto kvalifikátory vestavěné v knihovně android.hilt:hilt-android. @ActivityContext je k dispozici pouze v modulech nainstalovaných v ActivityComponent.
@Binds — účinná alternativa k @Provides, když metoda přijímá přesně jeden parametr a vrací jeho typ jako rozhraní. @Binds generuje přímé přetypování bez volání metody, což snižuje množství generovaného kódu a zvyšuje výkon při vkládání.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také