Skip to content

Hilt

Developer UtilitiesDependency InjectionKotlin

What it is

Hilt is Android's recommended dependency injection framework, built on Dagger with a simplified API and Android lifecycle-aware components.

Annotate the Application with @HiltAndroidApp, provide dependencies in modules scoped to a component, and inject with @Inject or @HiltViewModel.

Installation

implementation("com.google.dagger:hilt-android:2.52")

Getting started

The smallest useful thing you can do with it, and what each part means.

Modules and scopes
@HiltAndroidApp
class MyApp : Application()

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

    @Provides
    fun provideBookDao(db: AppDatabase): BookDao = db.bookDao()
}

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
    @Binds
    abstract fun bindBookRepository(impl: RoomBookRepository): BookRepository
}

@HiltViewModel
class BookViewModel @Inject constructor(
    private val repository: BookRepository,
) : ViewModel()
@Binds is more efficient than @Provides for interface-to-implementation mapping — it generates no factory method, just a type alias in the graph.

Advanced usage

Where the library earns its place over a simpler alternative.

Qualifiers and test replacement
@Qualifier @Retention(AnnotationRetention.BINARY)
annotation class AuthenticatedClient

@Provides @AuthenticatedClient
fun provideAuthClient(interceptor: AuthInterceptor): OkHttpClient = ...

class ApiService @Inject constructor(
    @AuthenticatedClient private val client: OkHttpClient,
)

// Swap the whole module in instrumented tests.
@UninstallModules(DataModule::class)
@HiltAndroidTest
class BookRepositoryTest {
    @get:Rule val hiltRule = HiltAndroidRule(this)

    @Module @InstallIn(SingletonComponent::class)
    object FakeDataModule {
        @Provides fun provideDao(): BookDao = FakeBookDao()
    }
}
@UninstallModules with a replacement is Hilt's testing story: the real graph is swapped at the module level rather than by injecting fakes manually through every constructor.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

cannot be provided without an @Inject constructor or @Provides
The type is not in the graph. Add a @Provides or @Binds, or annotate its constructor.
Build times increased sharply
Annotation processing. Migrate from kapt to KSP, which is substantially faster.

Best practices

  • Use @Binds rather than @Provides when simply mapping an interface to an implementation.
  • Scope carefully — @Singleton on something holding an Activity context leaks it.
  • Use qualifiers when two bindings share a type rather than wrapping one in a marker class.
  • Choose Koin instead if build speed matters more than compile-time verification.

Background

Why it exists, and what it was reacting to.

Dagger is powerful and notoriously hard to set up on Android. Hilt provides the standard component hierarchy — application, activity, fragment, view model — so teams stop writing it themselves.