Implement Hilt for Android app using Kotlin

Pragnesh Ghoda
4 min readJan 26, 2023

--

What is Hilt, Dependency injection, and How to implement Hilt for Android using Kotlin?

Photo Credit: Satya Pavan Kantamani

What is Dependency injection?

Dependency injection is a design pattern that allows you to separate the concerns of creating and managing objects in your code. It makes it easy to manage the dependencies between different classes and modules in your app and promotes the development of loosely coupled, testable, and maintainable code.

What is Hilt?

Hilt is a dependency injection library for Android that is built on top of the popular Dagger library. It is a part of the Android Jetpack libraries and was introduced by Google.

Hilt is designed to make it easy to implement dependency injection in Android apps, with minimal boilerplate code and a focus on best practices for clean code and maintainability. It also provides a set of additional features and annotations to make it easy to integrate with other Android Jetpack libraries and use cases such as ViewModel, WorkManager, and Navigation.

Hilt uses annotations and code generation to handle the creation and management of objects, so you don’t have to write a lot of boilerplate code. It also automatically handles the lifecycle of objects based on the lifecycle of the Android components, such as activities and fragments, so you don’t have to worry about managing the lifecycle of objects yourself.

How to implement Hilt

Here are the steps for implementing Hilt in an Android app using Kotlin and MVVM architecture:

  1. First, add the hilt-android-gradle-plugin plugin to your project’s root build.gradle file:
plugins {
...
//To configure the Hilt Gradle plugin with Gradle's new plugins DSL
id("com.google.dagger.hilt.android") version "2.44" apply false
}

buildscript {
repositories {
// other repositories...
mavenCentral()
}
dependencies {
// other plugins...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44.2'
}
}

2. Add the Hilt dependencies to the app-level build.gradle file

plugins {
kotlin("kapt")
id("com.google.dagger.hilt.android")
}

android {
...
// Hilt uses Java 8 features. To enable Java 8 in your project, add the following lines
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}

dependencies {
implementation("com.google.dagger:hilt-android:2.44")
kapt("com.google.dagger:hilt-android-compiler:2.44")

// OPTIONAL: For instrumentation tests
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.44.2'
kaptAndroidTest 'com.google.dagger:hilt-compiler:2.44.2'

// OPTIONAL: For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.44.2'
kaptTest 'com.google.dagger:hilt-compiler:2.44.2'
}

// Allow references to generated code
kapt {
correctErrorTypes = true
}

Hilt currently supports the following Android classes

  • Application (by using @HiltAndroidApp)
  • ViewModel (by using @HiltViewModel)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

3. Annotate the application class with @HiltAndroidApp. This will automatically generate the necessary code for Hilt to work.

@HiltAndroidApp
class MyApplication : Application() {
//...
}

4. Annotate the activities, fragments, and ViewModel with @AndroidEntryPoint. This will automatically generate the necessary code for Hilt to work.

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
}

If you annotate an Android class with @AndroidEntryPoint, then you also must annotate Android classes that depend on it. For example, if you annotate a fragment, then you must also annotate any activities where you use that fragment.

5. Create a module for each class that needs to be injected. Modules are used to define the dependencies that Hilt should provide.

Annotate the module with @Module and use @Provides and @Binds to define the dependencies.

// Service module, can be created separate or can create common for all
@Module
@InstallIn(SingletonComponent::class)
class MainServicesModule {
@Provides
@Singleton
fun provideMainService(@RefreshTokenRetrofit retrofit: Retrofit): MainService {
return NetworkClient.createApiService(retrofit)
}
}

// Usecase module, can be created separate or can create common for all
@Module
@InstallIn(SingletonComponent::class)
abstract class MainUseCasesModule {
@Binds
abstract fun provideMainMenuUseCase(getMainMenuUseCase: GetMainMenuUseCaseImpl): GetMainMenuUseCase
}

6. Use the @Inject annotation to indicate which fields and constructors should be injected.

@HiltViewModel
class MainViewModel @Inject constructor(
private val application: Application
) : ViewModel()

7. That’s it! Hilt will automatically generate the necessary code to inject the dependencies at runtime.

It’s important to note that Hilt doesn’t force you to use any particular architecture. You can use MVVM, MVP, or any other architecture with Hilt. The main goal is to make it easier to implement dependency injection and promote clean code and maintainability.

Thanks for reading this article. Hope you would have liked it!. Please clap, share, and subscribe to my blog to support.

References:

https://dagger.dev/hilt

https://developer.android.com/training/dependency-injection/hilt-android#kts

--

--