← Back to list

Demystifying Hilt: How and Why Objects Flow Through Your Android App

What is Hilt?

kanhaiya yadav · 2026-05-13 19:34 · 0 claps · 4.1 min read
#hilts #android-hilt
Open on Medium ↗

Demystifying Hilt: How and Why Objects Flow Through Your Android App

What is Hilt?

Hilt is Dependency Injection library for android built on top of Dagger. We can think of Hilt as a system that automatically creates and provides the object your app needs, instead of you manually creating and passing them around everywhere.

Before understanding how Hilt helps us, let’s first see how dependency creation is usually handled without any Dependency Injection library.

Suppose we have an app that fetches user data from an API.

class ApiService {

    fun getUsers(): List<String> {
        return listOf("John", "Emma", "Alex")
    }
}

class UserRepository {

    private val apiService = ApiService()

    fun fetchUsers(): List<String> {
        return apiService.getUsers()
    }
}

class MainViewModel {

    private val repository = UserRepository()

    fun loadUsers() {
        val users = repository.fetchUsers()
        println(users)
    }
}

MainViewModel creates UserRepository. UserRepository creates ApiService.Each class is responsible for creating its own dependencies.This may look fine for small projects, but as the application grows, it starts creating problems.

Problems Without DI

  • Tight Coupling: MainViewModel is tightly coupled to UserRepository.UserRepository is tightly coupled to ApiService.This makes the code less flexible and harder to modify.
  • Difficult Testing:Imagine you want to test MainViewModel.You cannot easily replace the real UserRepository or ApiService with fake/mock versions because the objects are created internally.
  • Duplicate Object Creation: Every time a new class creates ApiService, a new instance is created.In real apps, this can waste memory and resources.

The Core Problem

The main issue is:Classes should not be responsible for creating their own dependencies.They should only focus on their actual job.UserRepository should manage user data not decide how ApiService is created. This is exactly where Dependency Injection and Hilt help us.

A Better Approach — Dependency Injection

Instead of creating dependencies inside the class, we provide them from outside.

class UserRepository(
    private val apiService: ApiService
)

Now UserRepository no longer cares:

  • where ApiService comes from
  • how it is created
  • whether it is a real or fake implementation

It simply receives what it needs and focuses only on its responsibility.This concept is called Dependency Injection (DI).

Where Hilt Comes In

Dependency Injection improves architecture, but managing dependencies manually can still require a lot of boilerplate code. This is where Hilt helps.

Hilt automates:

  • object creation
  • dependency management
  • lifecycle handling
  • dependency sharing

so developers can focus more on building features instead of wiring dependencies manually.

Setting Up Hilt in an Android Project

Now that we understand the basics of Dependency Injection, let’s set up Hilt in an Android project and understand why each configuration is required.

Hilt works on top of Dagger and generates a lot of code automatically during compilation. That’s why some setup is necessary before we can start injecting dependencies.

Step 1 — Add Hilt Dependencies

Project-Level build.gradle

plugins {
    id("com.google.dagger.hilt.android") version "2.57.1" apply false
}

This adds the Hilt Gradle plugin to the project.The plugin is responsible for:

  • generating dependency injection code
  • creating Hilt components automatically
  • connecting Android lifecycle components with Dagger

Without this plugin:

  • Hilt annotations like @HiltViewModel
  • @AndroidEntryPoint
  • @HiltAndroidApp

would not work because the required generated code would never be created.

Step 2 — Add Hilt Dependencies in App Module

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")

    // KSP plugin for annotation processing
    id("com.google.devtools.ksp")

    // Hilt Gradle plugin
    id("com.google.dagger.hilt.android")
}

dependencies {

    // Main Hilt library
    implementation("com.google.dagger:hilt-android:2.57.1")

    // Hilt compiler for code generation
    ksp("com.google.dagger:hilt-compiler:2.57.1")

    // Hilt support for Jetpack Compose Navigation
    implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
}

Hilt Gradle Plugin

id("com.google.dagger.hilt.android")

This plugin connects Hilt with the Android build system.It is responsible for:

  • generating dependency injection code
  • creating Hilt components automatically
  • integrating Hilt with Android lifecycle classes

Without this plugin:

  • annotations like @AndroidEntryPoint
  • @HiltViewModel
  • @HiltAndroidApp

will not work correctly because the required generated code will be missing.

Main Hilt Library

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

This is the core Hilt library.It contains:

  • Hilt annotations
  • dependency injection APIs
  • Android integration support
  • lifecycle-aware components

This library gives us access to features like:

  • @Inject
  • @HiltViewModel
  • @AndroidEntryPoint

Without it, Hilt functionality is unavailable.

Hilt Compiler

ksp("com.google.dagger:hilt-compiler:2.57.1")

Hilt works using code generation.

The compiler:

  • reads annotations like @Inject
  • analyzes dependency relationships
  • generates factories and dependency graphs automatically

For example, when Hilt sees:

@Inject constructor()

it generates the code required to create that object automatically.

Without the compiler:

  • Hilt cannot generate dependency code
  • injection will fail at compile time

Hilt Navigation Compose

implementation("androidx.hilt:hilt-navigation-compose:1.2.0")

This dependency provides Hilt integration with Jetpack Compose navigation.

It allows us to use ViewModels easily inside Compose screens:

val viewModel: UserViewModel = hiltViewModel()

Step 3 — Create the Application Class

@HiltAndroidApp
class MyApplication : Application()

Why Is @HiltAndroidApp Required?

This is one of the most important annotations in Hilt.

When you add:

@HiltAndroidApp

Hilt generates:

  • the application-level dependency container
  • the root Dagger component

Think of it as:“Start Hilt for the entire app.”

Without this annotation:

  • Hilt cannot initialize
  • dependency injection will not work anywhere in the app

Step 4 — Register Application Class in Manifest

<application
    android:name=".MyApplication"
    ...
</application>

Why Is This Required?

Android must know which Application class to start when the app launches.

If we don’t register it:

  • Android uses the default Application
  • Hilt initialization never happens

So even though we created MyApplication, Android would ignore it.

Step 5 — Create a Repository

class UserRepository @Inject constructor() {

    fun getUsers(): List<String> {
        return listOf("John", "Emma", "Alex")
    }
}

Why Is @Inject constructor() Required?

This tells Hilt:“You are allowed to create this class automatically.”

Without @Inject:

  • Hilt does not know how to construct UserRepository

Hilt needs instructions for creating dependencies.

Step 6 — Create ViewModel with @HiltViewModel

@HiltViewModel
class UserViewModel @Inject constructor(
    private val repository: UserRepository
) : ViewModel() {

    fun loadUsers(): List<String> {
        return repository.getUsers()
    }
}

Why Is @HiltViewModel Required?

ViewModels are managed by Android’s lifecycle system.Normally Android creates ViewModels itself.

Hilt needs this annotation to:

  • integrate with the ViewModel lifecycle
  • create the ViewModel using dependency injection
  • survive configuration changes properly

Without @HiltViewModel:

  • Hilt cannot inject dependencies into the ViewModel

Step 7 — Enable Injection in Activity

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: UserViewModel by viewModels()
}

Why Is @AndroidEntryPoint Required?

Android components like:

  • Activity
  • Fragment
  • Service

are created by the Android framework, not by Hilt. So Hilt needs permission to inject dependencies into them.

@AndroidEntryPoint tells Hilt:“This Android class participates in dependency injection.”Without it:

  • injected dependencies cannot be provided
  • ViewModel injection will fail

What Happens Behind the Scenes?

When the app starts:

  1. Hilt initializes the dependency container
  2. Hilt generates dependency graphs
  3. Hilt creates UserRepository
  4. Hilt creates UserViewModel
  5. Hilt injects dependencies automatically
  6. Android receives ready-to-use objects

All of this happens with minimal boilerplate.


메타데이터
post_id
40e40b623cdc
slug
demystifying-hilt-how-and-why-objects-flow-through-your-android-app-40e40b623cdc
url
https://medium.com/@kanhaiya.yadav47/demystifying-hilt-how-and-why-objects-flow-through-your-android-app-40e40b623cdc
canonical_url
https://medium.com/@kanhaiya.yadav47/demystifying-hilt-how-and-why-objects-flow-through-your-android-app-40e40b623cdc
author_url
https://medium.com/@kanhaiya.yadav47
status
ok
fetched_at
2026-06-24 04:09:36