MyFamilyTracker
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
A from-the-ground-up guide to Hilt on Android — what dependency injection actually buys you, the core annotations, how to provide and scope dependencies, and the small set of rules that keep DI from turning into a maze.
On this page
Dependency injection sounds like an enterprise word for a simple idea: instead of an object creating the things it depends on, those things are handed to it. Hilt is Google's standard way to do that on Android, built on top of Dagger but with most of the boilerplate removed. If you've avoided it because Dagger scared you, Hilt is worth a fresh look — it does the wiring so you can spend your attention on the app.
The honest answer is testability and decoupling. When a
ViewModelThe second benefit is that object creation stops being scattered everywhere. Without DI, the knowledge of how to build a repository lives in every place that builds one. With Hilt, it lives in one module, and everyone asks for the finished object. As an app grows, that centralization is the difference between a wiring diagram you can follow and a tangle you can't.
Hilt's surface is small once you see the pattern. You mark your
Application@HiltAndroidApp
class MyApp : Application()You mark the Android entry points that need injection:
@AndroidEntryPoint
class MainActivity : ComponentActivity() { /* ... */ }And you mark a ViewModel so Hilt provides its constructor dependencies:
@HiltViewModel
class HomeViewModel @Inject constructor(
private val repository: UserRepository,
) : ViewModel()The
@Inject constructorHilt can build any class with an
@Inject@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideApi(): UserApi = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.build()
.create(UserApi::class.java)
}For binding an interface to its implementation,
@Binds@Provides@Module
@InstallIn(SingletonComponent::class)
abstract class RepoModule {
@Binds
abstract fun bindUserRepo(impl: UserRepositoryImpl): UserRepository
}A scope answers "how long does this object live and who shares it."
@Singleton@ActivityRetainedScoped@ViewModelScopedHilt only becomes a maze if you let it. Three habits keep mine readable. First, prefer constructor injection everywhere; field injection is only for framework classes you don't construct yourself. Second, keep modules small and named for what they provide — a
NetworkModuleDatabaseModuleAppModuleOne last thing worth internalizing: Hilt rewards consistency more than cleverness. Across many apps, the value isn't any single advanced feature — it's that every project wires its dependencies the same predictable way, so moving between codebases costs nothing. When a new developer (or a future you) opens the project, the dependency graph is discoverable from the annotations rather than buried in hand-written factories. That predictability is the real return on adopting a DI framework, and it only holds if you keep using the simple, conventional patterns instead of inventing bespoke wiring for each app. Boring and uniform is exactly what you want from the layer that holds everything else together.
@HiltAndroidApp@AndroidEntryPoint@HiltViewModel@Inject constructor@Binds@ProvidesSudarshan Chaudhari
AI Systems Builder / Product Engineer
Bangkok, Thailand
Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.
Related Posts
Related Apps
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Building something? Available for Android dev and QA consulting.
Work with meComments — powered by Giscus
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
ReadPrivate dream journal — structured entry capture, pattern tagging, and optional Claude-powered insight generation. All data stays on-device by default.
ReadWorkout tracker — exercise logging with set/rep/weight history, goal progression, and local Room DB persistence. No account, no cloud sync required.
Read