0Pricing
Android Academy · Lesson

Dependency Injection with Hilt

Simplify dependency management with Hilt. Use @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel, @Module, @Provides, and @Singleton scopes.

Dependency Injection with Hilt is a free Android Academy lesson on CoddyKit — lesson 6 of 6. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 6 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is Dependency Injection?

Dependency Injection (DI) means providing an object with what it needs rather than having it create dependencies itself.

Without DI, a class creates its own dependencies — tightly coupled, hard to test. With DI, dependencies are injected from outside — loosely coupled, easy to test and swap.

Manual DI vs Hilt

Manual DI works but becomes painful at scale:

// Manual DI — you create and pass everything:
val db = AppDatabase.getInstance(context)
val dao = db.userDao()
val repo = UserRepository(dao)
val factory = UserViewModel.Factory(repo)
val viewModel = ViewModelProvider(this, factory)[UserViewModel::class.java]

// With Hilt:
// Just annotate, Hilt does the wiring
@HiltViewModel
class UserViewModel @Inject constructor(private val repo: UserRepository) : ViewModel()

Adding Hilt

Add Hilt to your project:

// project/build.gradle:
buildscript {
    dependencies {
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.51'
    }
}

// app/build.gradle:
plugins {
    id 'com.google.dagger.hilt.android'
    id 'kotlin-kapt'
}

dependencies {
    implementation 'com.google.dagger:hilt-android:2.51'
    kapt 'com.google.dagger:hilt-android-compiler:2.51'
}

@HiltAndroidApp

Annotate your Application class with @HiltAndroidApp. This is the entry point for the Hilt component hierarchy:

@HiltAndroidApp
class MyApp : Application()

// Also register in AndroidManifest.xml:
// <application android:name=".MyApp" ...>

@AndroidEntryPoint

Add @AndroidEntryPoint to Activities, Fragments, and Services that need injected dependencies:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var analytics: AnalyticsService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        analytics.logEvent("app_open")
    }
}

@AndroidEntryPoint
class HomeFragment : Fragment() {
    // Fragment's parent Activity must also be @AndroidEntryPoint
}

@Inject — Constructor Injection

Mark the constructor with @Inject to tell Hilt how to create the class. Hilt automatically resolves all parameters:

class UserRepository @Inject constructor(
    private val userDao: UserDao,
    private val apiService: ApiService
) {
    suspend fun getUsers() = userDao.getAll()
    suspend fun syncFromNetwork() {
        val users = apiService.fetchUsers()
        userDao.insertAll(users)
    }
}

// Hilt sees UserRepository needs UserDao and ApiService,
// and automatically creates and injects them.

@HiltViewModel

Annotate your ViewModel with @HiltViewModel and use @Inject constructor. In the Fragment, get it with by viewModels():

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

    val users = repo.getUsersFlow().asLiveData()
}

// In Fragment:
@AndroidEntryPoint
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()  // Hilt provides it
}

@Module & @Provides

When Hilt can't use constructor injection (e.g., interfaces, third-party classes), provide instances via a @Module:

@Module
@InstallIn(SingletonComponent::class)   // lives for app lifetime
object NetworkModule {

    @Provides
    @Singleton
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }
}

@Binds — Interface Binding

Use @Binds to tell Hilt which implementation to use for an interface:

interface AnalyticsService {
    fun logEvent(name: String)
}

class FirebaseAnalytics @Inject constructor() : AnalyticsService {
    override fun logEvent(name: String) { /* Firebase impl */ }
}

@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {

    @Binds
    @Singleton
    abstract fun bindAnalytics(impl: FirebaseAnalytics): AnalyticsService
}

Hilt Scopes

Scopes control how long an injected instance lives:

  • @Singleton — one instance for the app's lifetime (ApplicationComponent)
  • @ActivityRetainedScoped — survives configuration changes
  • @ActivityScoped — one instance per Activity
  • @FragmentScoped — one instance per Fragment
  • @ViewModelScoped — one instance per ViewModel

Testing with Hilt

Replace real dependencies with fakes in tests using Hilt's test support:

@HiltAndroidTest
class UserRepositoryTest {

    @get:Rule
    val hiltRule = HiltAndroidRule(this)

    @Inject
    lateinit var repo: UserRepository

    @Before
    fun setUp() {
        hiltRule.inject()
    }

    @Test
    fun usersAreFetched() {
        assertNotNull(repo)
    }
}

Quick Check

Which annotation tells Hilt to generate the DI component hierarchy for your entire application?

Recap: Hilt Dependency Injection

Hilt makes DI almost automatic in Android:

  • @HiltAndroidApp on your Application class
  • @AndroidEntryPoint on Activities and Fragments
  • @Inject constructor for injectable classes
  • @HiltViewModel + @Inject constructor for ViewModels
  • @Module + @Provides for third-party classes and interfaces
  • @Singleton to share one instance app-wide

Next: push notifications with Firebase Cloud Messaging.

Frequently asked questions

Is the “Dependency Injection with Hilt” lesson free?

Yes — the full text of “Dependency Injection with Hilt” is free to read here on the web, and the Android Academy course includes 6 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.

What will I learn in “Dependency Injection with Hilt”?

Simplify dependency management with Hilt. Use @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel, @Module, @Provides, and @Singleton scopes. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 6 of 6, so you can start here or from the beginning and move at your own pace.

How long does the “Dependency Injection with Hilt” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. ViewModel & LiveData
  2. Room Database
  3. Coroutines & Suspend Functions
  4. Repository Pattern
  5. Navigation Component
  6. Dependency Injection with Hilt
← Back to Android Academy