← All courses

Dependency Injection with Hilt

🗓 May 31, 2026 ⏱ 2 min read

What is dependency injection?

“Dependency injection” (DI) sounds scary but means something simple: instead of a class creating the objects it needs, those objects are given to it. This makes classes easier to test (you can pass in fakes) and removes messy manual wiring.

Without DI, a ViewModel might do val repo = UserRepository(ApiService(), UserDao()) — and now it’s tied to exact implementations. With DI, the repository is simply handed in.

Hilt: DI made easy for Android

Hilt is Google’s DI library built on Dagger. You annotate things, and Hilt generates all the wiring.

// 1. mark your Application
@HiltAndroidApp
class MyApp : Application()

// 2. tell Hilt how to provide things
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    @Provides @Singleton
    fun provideApi(): ApiService =
        Retrofit.Builder().baseUrl("https://api.example.com/")
            .addConverterFactory(MoshiConverterFactory.create())
            .build().create(ApiService::class.java)
}

Injecting into a ViewModel

@HiltViewModel
class UsersViewModel @Inject constructor(
    private val repo: UserRepository
) : ViewModel() { /* ... */ }

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: UsersViewModel by viewModels()
}

Hilt sees the constructor needs a UserRepository, which needs an ApiService, and builds the whole chain for you.

Common mistakes

  • Forgetting @HiltAndroidApp on the Application class.
  • Forgetting @AndroidEntryPoint on the Activity/Fragment.
  • Over-using @Singleton — only share objects that are genuinely app-wide.
Summary: DI means “objects are given, not created”. Hilt automates the wiring with a few annotations, making your app cleaner and far easier to test.