Dagger — är ett ramverk för beroendeinjektion för Java och Kotlin som genererar DI-kod vid kompilering genom annoteringsbearbetning. Hilt — är ett lager ovanpå Dagger för Android som förenklar konfigurationen av komponenter och livscykel. Enligt Google, 2025 används Hilt i mer än 70% av Android-apparna från Google Play Top-100, med stöd för Activity, Fragment, ViewModel och Service via fördefinierade komponenter. Båda ramverken säkerställer kontroll av beroendegrafen vid kompilering, vilket eliminerar runtime-injektionsfel.
Huvudpunkter
Dagger — är ett ramverk för beroendeinjektion med kodgenerering vid kompilering (compile-time DI). Utvecklat på Square och senare överlämnat till Google, använder Dagger Java APT-annoteringsprocessorn för att analysera beroendegrafen och generera fabriksklasser. Till skillnad från runtime-DI (Guice, Koin) använder Dagger inte reflektion — all kod skapas vid kompilering, vilket ger maximal prestanda vid körning och felupptäckt i byggfasen.
Hilt — är ett bibliotek från Google, byggt ovanpå Dagger och optimerat för Android. Hilt tillhandahåller fördefinierade komponenter som motsvarar livscykeln för Android-komponenter: @SingletonComponent för Application, @ActivityComponent för Activity, @FragmentComponent för Fragment, @ViewModelComponent för ViewModel. Detta eliminerar den rutinmässiga konfigurationen av Component och Module som krävs i ren Dagger. Hilt genererar också automatiskt beroendegrafen för varje Android-komponent via @AndroidEntryPoint.
Enligt Google I/O 2024 är Hilt den rekommenderade DI-lösningen för Android-appar skrivna i Kotlin. Jetpack-biblioteken (Navigation, Room, WorkManager) har inbyggd integration med Hilt via @HiltViewModel och @HiltWorker. I projekt som inte använder Android (rena Java/Kotlin-bibliotek, serverapplikationer) används ren Dagger utan Hilt-lager.
Utan DI-ramverk skapar utvecklaren objekt manuellt via konstruktorer eller fabriker och skickar beroenden längs kedjan. Varje nytt krav — ändring av signatur för alla konstruktorer i kedjan. Dagger automatiserar denna process: det räcker att deklarera vilken typ som krävs (@Inject constructor), och Dagger skapar beroendegrafen och löser alla kapslade typer. När beroenden ändras uppdaterar Dagger automatiskt den genererade koden — det är omöjligt att göra fel i kedjan.
Beroendeinjektion (Dependency Injection) — är ett mönster där ett objekt tar emot sina beroenden utifrån, istället för att skapa dem själv. DI implementerar principen om inversion av kontroll (IoC): klassen är inte ansvarig för att skapa sina egna beroenden, utan deklarerar dem via konstruktor, metod eller fält. Injektion via konstruktor (constructor injection) anses vara den mest föredragna metoden eftersom den garanterar att objektet skapas i ett giltigt tillstånd.
| Injektionstyp | Dagger-syntax | När ska den användas |
|---|---|---|
| Constructor injection | @Inject constructor | Huvudmetod — för alla egna klasser |
| Field injection | @Inject lateinit var | Endast för Android-komponenter (Activity, Fragment) |
| Method injection | @Inject fun bind() | För post-construct-initiering |
De främsta fördelarna med DI inkluderar testbarhet (beroenden kan ersättas med mock-objekt), lös koppling (klasser beror på gränssnitt, inte implementeringar) och explicit hantering av objekts livscykel via scopar. Dagger garanterar automatiskt att ett objekt skapas en gång inom sitt scope och förstörs när scopet lämnas.
Component — den centrala delen av Dagger-beroendegrafen. Det är ett gränssnitt annoterat med @Component som beskriver bron mellan Module och injektionsmål. Dagger genererar implementeringen av Component (t.ex. DaggerAppComponent) vid kompilering. Component bestämmer vilka typer som är tillgängliga för injektion, via abstrakta metoder som returnerar de nödvändiga typerna eller via inject-metoder som tar emot ett objekt för field injection.
// Modul: tillhandahåller beroenden som Dagger inte kan skapa själv
@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)
}
}
// Komponent: kopplar samman Module och injektionsmål
@Component(modules = [NetworkModule::class])
interface AppComponent {
fun inject(activity: MainActivity)
fun getApiService(): ApiService
}
@Module — är en klass som innehåller metoder med @Provides som returnerar instanser av beroenden. Module används för typer som Dagger inte kan skapa automatiskt: tredjepartsbibliotek (OkHttp, Retrofit), objekt med konstruktorparametrar, gränssnitt med implementeringsval. @Binds — ett alternativ till @Provides i fall där metoden returnerar ett gränssnitt och tar emot en enda implementering: Dagger genererar en direkt omvandling utan att anropa metoden.
@Scope bestämmer objektets livslängd i beroendegrafen. @Singleton — objektet skapas en gång för hela appen. @ActivityScoped — objektet lever så länge Activity lever. @FragmentScoped — så länge Fragment lever. Utan scope skapar Dagger en ny instans vid varje injektion. @Reusable — scope för objekt som inte måste vara singlar men vars skapande är kostsamt — Dagger kan cachelagra instansen, men garanterar inte detta.
Hilt förenklar konfigurationen av Dagger för Android tack vare fördefinierade komponenter och automatisk generering av basgrafen. Annotationen @HiltAndroidApp på Application-klassen aktiverar genereringen av Hilt-komponenten. Utan denna annotation fungerar inte Hilt — den är obligatorisk för varje Android-app som använder Hilt. @HiltAndroidApp skapar föräldrakomponenten SingletonComponent, från vilken alla andra komponenter i appen ärver.
@HiltAndroidApp
class MyApplication : Application()
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var apiService: ApiService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// apiService har redan injicerats före anropet till 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 — annotation för Activity, Fragment, Service, BroadcastReceiver och View. Genererar en Hilt-komponent för varje typ: @AndroidEntryPoint på Activity skapar ActivityComponent som ärver från SingletonComponent. Barnkomponenten tar automatiskt emot alla beroenden från föräldern. Field injection med @Inject lateinit var är endast tillgänglig i klasser annoterade med @AndroidEntryPoint — i vanliga klasser används constructor injection.
@InstallIn anger i vilken Hilt-komponent modulen installeras. NetworkModule med @InstallIn(SingletonComponent::class) är tillgängligt i hela appen. Module med @InstallIn(ActivityComponent::class) — endast i Activity. Detta isolerar beroendegrafer: Activity-specifika moduler är inte synliga i Fragment och ViewModel, vilket förhindrar oavsiktlig användning av otillåtna beroenden. @ApplicationContext — den inbyggda Hilt-kvalificeraren för att erhålla applikationskontexten.
När två olika implementeringar av samma gränssnitt behöver injiceras, används kvalificerare. Hilt stöder @Named för textidentifierare och anpassade annotationer med @Qualifier. Till exempel @Named("baseUrl") och @Named("imageBaseUrl") för olika textkonfigurationer. Anpassade kvalificerare är att föredra framför @Named på grund av kontroll vid kompilering — ett felaktigt textnamn upptäcks inte förrän vid körning.
@HiltViewModel — annotation som ersätter den manuella fabriken ViewModelProvider.Factory. En klass annoterad med @HiltViewModel med @Inject constructor tar automatiskt emot alla beroenden via Dagger. Hilt genererar ViewModelFactory som används av Jetpack ViewModelProvider. Utan Hilt skulle utvecklaren behöva skriva fabriken manuellt och skicka varje parameter från Activity eller fragment.
@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()
}
}
}
// I Activity — Hilt skapar automatiskt ViewModel
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
}
ViewModelScoped — Hilt-scope för beroenden som lever så länge ViewModel lever. Om två ViewModels av samma typ injicerar samma @ViewModelScoped-beroende, får var och en sin egen instans. Detta skiljer @ViewModelScoped från @ActivityScoped, där en Activity får en instans för alla fragment. För ViewModel-specifika beroenden (t.ex. SavedStateHandle) använd @HiltViewModel med @Inject constructor(savedStateHandle: SavedStateHandle).
Hilt stöder assisted injection via Hilt Extensions-biblioteket. Assisted injection gör det möjligt att skicka parametrar till konstruktorn under injektion, när en del av beroendena endast är kända vid körning (t.ex. användar-ID från intent). För assisted injection används @AssistedInject i kombination med @Assisted-parametrar. Hilt genererar AssistedFactory som kan injiceras på standard sätt.
Ren Dagger kräver manuell skapelse av Component, definition av scopar och konfiguration av injektion i varje Android-komponent. Utvecklaren skapar AppComponent, ActivityComponent, FragmentComponent och hanterar deras relationer via @Subcomponent. Detta tillvägagångssätt ger maximal kontroll men kräver en betydande mängd boilerplate-kod. Dagger används i stora projekt där en anpassad DI-arkitektur krävs, eller i icke-Android Java/Kotlin-projekt.
Hilt automatiserar boilerplate: en @HiltAndroidApp, en @AndroidEntryPoint för varje komponent, fördefinierade scopar. Hilt rekommenderas av Google för alla nya Android-projekt. Migrering från Dagger till Hilt inkluderar att ersätta Component med @InstallIn, ersätta @Subcomponent med fördefinierade Hilt-komponenter och ersätta manuell ViewModelProvider.Factory med @HiltViewModel. De flesta @Module-klasser överförs med tillägg av @InstallIn utan att ändra @Provides-metoderna.
| Egenskap | Dagger | Hilt |
|---|---|---|
| Konfiguration | Manuell: Component, Subcomponent, Builder | Automatisk: @HiltAndroidApp, @AndroidEntryPoint |
| Android-komponenter | Inga fördefinierade | 12+ inbyggda komponenter |
| ViewModel | Manuell fabrik | @HiltViewModel + @Inject constructor |
| Multimodul | Via @Component(dependencies) | Via @InstallIn + aggregering |
| Komplexitet | Hög — kräver erfarenhet | Låg — intuitiv |
| Flexibilitet | Maximal | Standard (täcker 95% av scenarierna) |
Begränsningar för Hilt: biblioteket stöder endast Android (inte lämpligt för rena server-Java-projekt), påtvingar en viss komponentstruktur (svår att åsidosätta) och lägger till ett beroende av android.hilt:hilt-navigation-compose för Jetpack Compose-projekt. För Compose-appar tillhandahåller Hilt @HiltViewModel tillgänglig i Composable via hiltViewModel() — utan manuell tillhandahållning av ViewModel från Activity.
Vanliga frågor
Dagger — grundläggande compile-time DI-ramverk med manuell konfiguration av Component och Module. Hilt — Android-lager som automatiserar skapandet av komponenter och integration med livscykeln för Activity, Fragment, ViewModel, Service och BroadcastReceiver.
@HiltAndroidApp aktiverar genereringen av Hilt-komponenten för Application. Utan denna annotation kan Hilt inte skapa baskomponenten SingletonComponent, från vilken alla ActivityComponent, FragmentComponent och ViewModelComponent ärver. Annotationen är obligatorisk för varje Hilt-projekt.
Hilt Navigation tillhandahåller @HiltViewModel för ViewModel i NavBackStackEntry och hiltNavGraphViewModels() för att scopa ViewModel inom navigeringsgrafen. Biblioteket android.hilt:hilt-navigation-fragment skapar automatiskt ViewModel för varje NavBackStackEntry.
Använd @ApplicationContext för applikationskontexten eller @ActivityContext för Activity-kontexten. Hilt tillhandahåller dessa kvalificerare inbyggda i biblioteket android.hilt:hilt-android. @ActivityContext är endast tillgänglig i moduler installerade i ActivityComponent.
@Binds — ett effektivt alternativ till @Provides, när metoden tar emot exakt en parameter och returnerar dess typ som ett gränssnitt. @Binds genererar en direkt omvandling utan att anropa metoden, vilket minskar mängden genererad kod och ökar prestandan vid injektion.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också