Dependency Setup
Add the following dependencies to your module-level build.gradle file:
dependencies {
implementation("com.google.dagger:hilt-android:2.44")
annotationProcessor("com.google.dagger:hilt-android-compiler:2.44")
}
Apply the Hilt plugin in the same file:
plugins {
id("com.android.application")
id("dagger.hilt.android.plugin")
}
In the project-level build.gradle file, include the Hilt Gradle plugin in the buildscript dependencies:
buildscript {
dependencies {
classpath("com.google.dagger:hilt-android-gradle-plugin:2.44")
}
}
Application Class Configuration
Create a custom Application class annotated with @HiltAndroidApp. This annotation triggers Hilt's code generation and creates the necessary dependency injection infrastructure:
package com.example.di
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class DemoApplication : Application()
Register this application class in your AndroidManifest.xml file under the <application> tag.
Basic Dependency Injection
To make a class available for injection, annotate its constructor with @Inject. This tells Hilt how to create instances of this class:
package com.example.di
import javax.inject.Inject
class UserRepository @Inject constructor() {
fun getUserData(): String = "User data loaded successfully"
}
Inject dependencies into Android components using the @AndroidEntryPoint annotation and @Inject fields:
package com.example.di
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var userRepository: UserRepository
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("DI", userRepository.getUserData())
}
}
Hilt Modules
When you need to provide objects that cannot be cnostructor-injected (such as interfaces or third-party libraries), create a Hilt module using the @Module annotation:
package com.example.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideUserRepository(): UserRepository {
return UserRepository()
}
}
The @InstallIn annotation specifies which Hilt component the module should be installed into. The SingletonComponent is the highest-level component, meaning the provided dependency will be created once and shared across the entire application lifecycle.
Testing singleton behavior confirms proper module configuration:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var repository1: UserRepository
@Inject
lateinit var repository2: UserRepository
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("DI", repository1.toString())
Log.d("DI", "Same instance: ${repository1 === repository2}")
}
}
Default Hilt Components
Hilt provides several predefined components that correspond to different Android lifecycle scopes. The component hierarchy allows for proper scoping of dependencies:
| Component | Scope |
|---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
Activity or Fragment retained state |
ActivityComponent |
Activity |
FragmentComponent |
Fragment |
Context Injection with Qualifiers
Hilt allows injecting different types of Context using qualifiers. By default, @Inject uses the Application component:
class DataManager @Inject constructor(
private val repository: UserRepository,
private val appContext: Context,
private val application: Application
) {
fun getAppContextType(): String = appContext.javaClass.simpleName
fun getApplicationType(): String = application.javaClass.simpleName
}
To inject Activity-specific context, use the @ActivityContext qualifier:
class DataManager @Inject constructor(
private val repository: UserRepository,
@ActivityContext private val activityContext: Context
) {
fun getContextType(): String = activityContext.javaClass.simpleName
}
ViewModel Support with Hilt
Hilt provides first-class support for ViewModels. Add the following dependencies to enable ViewModel injection:
dependencies {
implementation("com.google.dagger:hilt-android:2.44")
annotationProcessor("com.google.dagger:hilt-android-compiler:2.44")
implementation("androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03")
annotationProcessor("androidx.hilt:hilt-compiler:1.0.0-alpha03")
}
Create a ViewModel with constructor injection using @ViewModelInject:
package com.example.di
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.ViewModel
class UserViewModel @ViewModelInject constructor(
private val repository: UserRepository
) : ViewModel() {
val userData: String = repository.getUserData()
}
Observe the ViewModel in your Activity or Fragment:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: UserViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("DI", viewModel.userData)
}
}
Hilt streamlines dependency injection in Android by eliminating boilerplate code and providing a standardized approach to managing dependencies across different application components.