Hands-On Guide to Learn Dependency Injection with Hilt for Kotlin Apps
In the fast-paced world of Android development, building scalable and maintainable apps is crucial. One of the key techniques to achieve this is dependency injection. If you want to streamline your Kotlin apps and reduce boilerplate code, learning dependency injection with Hilt is a must. In this guide, we will dive into Hilt, explain how it simplifies dependency management, and provide a hands-on approach to integrating it into your Kotlin applications.
What is Dependency Injection?
Before we dive into Hilt, it’s important to understand dependency injection (DI). Dependency injection is a design pattern used to reduce tight coupling between components in your app. It allows you to provide dependencies from the outside rather than creating them internally. By learning dependency injection with Hilt, developers can write cleaner, more modular code, and simplify testing for Android applications.
Why Use Hilt for Kotlin Apps?
Hilt is a dependency injection library built on top of Dagger, designed specifically for Android. Hilt simplifies the process of dependency injection by providing a standard way to incorporate DI into your app without extensive boilerplate code. If your goal is to learn dependency injection with Hilt, you’ll find that it integrates seamlessly with activities, fragments, view models, and more, making your code easier to manage and test.
Some benefits of using Hilt include:
- Automatic generation of Dagger components
- Built-in Android lifecycle integration
- Easier testing of dependencies
- Reduced boilerplate and faster setup
Setting Up Hilt in a Kotlin Project
To start learning dependency injection with Hilt, you first need to add the required dependencies in your build.gradle files. In your project-level build.gradle, ensure you have the following:
classpath "com.google.dagger:hilt-android-gradle-plugin:2.44"
Then, in your app-level build.gradle:
plugins {
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
dependencies {
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-android-compiler:2.44"
}
After syncing your project, you are ready to learn dependency injection with Hilt by creating modules and injecting dependencies.
Creating Hilt Modules
Modules in Hilt define how to provide dependencies. To demonstrate, let’s create a simple NetworkModule for Retrofit:
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
By learning dependency injection with Hilt, you can see how this module ensures that the Retrofit instance is shared across the app, reducing redundancy and improving maintainability.
Injecting Dependencies in Activities and Fragments
Once your module is ready, Hilt allows you to inject dependencies directly into your activities or fragments using the @AndroidEntryPoint annotation:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var retrofit: Retrofit
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
This is a core part of learning dependency injection with Hilt: the @Inject annotation eliminates manual initialization and enables a clean and concise setup.
Using Hilt with ViewModels
Hilt also simplifies dependency injection with ViewModels. By annotating your ViewModel with @HiltViewModel and using @Inject in its constructor, Hilt will handle providing dependencies automatically:
@HiltViewModel
class MainViewModel @Inject constructor(
private val repository: DataRepository
) : ViewModel() {
// ViewModel logic
}
This approach demonstrates a clean way to learn dependency injection with Hilt, allowing your ViewModels to receive dependencies without tightly coupling them to the data sources.
Testing with Hilt
Testing becomes straightforward when you learn dependency injection with Hilt. Hilt allows you to replace dependencies with mocks or fakes easily. For instance, you can create a test module that provides a fake repository to ensure your tests run in isolation without relying on network or database calls.
@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [NetworkModule::class]
)
object TestNetworkModule {
@Provides
fun provideFakeRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://fakeapi.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
Best Practices for Learning Dependency Injection with Hilt
- Always annotate your Android components with
@AndroidEntryPoint. - Keep your modules small and focused on providing specific dependencies.
- Avoid injecting too many dependencies into a single class; consider splitting responsibilities.
- Use Hilt’s
@Singletonscope wisely for shared resources. - Practice writing tests with Hilt to reinforce the concepts of DI.
Conclusion
Learning dependency injection with Hilt is essential for modern Kotlin Android development. Hilt simplifies the process of managing dependencies, reduces boilerplate code, and promotes modular, testable architecture. By setting up modules, injecting dependencies into activities, fragments, and ViewModels, and leveraging Hilt’s testing capabilities, developers can create scalable applications with ease. Mastering Hilt not only improves code quality but also accelerates development by providing a standardized, efficient way to handle dependencies, making it an indispensable skill for any Android developer looking to build robust Kotlin apps.



