Dagger-Hilt is part of the Jetpack library that assist in Dependency Injection (DI) framework. Recently I found it is very useful and want to share this useful knowledge to the community.
What is Dependency Injection (DI)?
Dependency Injection (DI) is a design pattern where it allows the creation of dependent objects outside of a class and provides these objects to a class through different ways.
A great example would be Car-Engine sample.
As mentioned on the diagram above, Without DI, every time when Car class is called, Engine will be initialized again. it is not a good example especially when creating a Singleton classes. To prevent these reinitialized problem, Engine should be moved out of Car class as a separated dependency.
When having a dependent Engine, it can be used (or we called inject) anytime that we want it to be used in Car class.
Besides, DI also helps in
- Reusability of code
- Ease of refactoring
- Ease of testing
Adding dependencies
First, add the hilt-android-gradle-plugin
plugin to your project's root build.gradle
file:
buildscript {
...
ext.hilt_version = '2.35'
dependencies {
...
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
}
}
Then, apply the Gradle plugin and add these dependencies in your app/build.gradle
file:
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'
android {
...
}
dependencies {
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"
}
Let’s implement in Android project!
There are many component for Android developer to choose from and each component is scoped to each corresponding lifecycle. For example, SingletonComponent
will be scoped for entire application lifecycle, while ViewModelComponent
will only scoped within ViewModel. When ViewModel destroyed, this component will be destroyed as well. Below is the complete table for every component with their corresponding scope.
Setting up all the Module
After learning these component and scope, we can first start to declare a Application Module to store all the SingletonComponent
which will last for the entire application’s lifecycle.
@InstallIn(SingletonComponent:class) — annotated as this module is bind to Application Lifecycle
@Singleton — annotated as this method only instantiates once.
@Provides — annotated as this method to create a provider method binding.
For using SingletonComponent
, the best use case is to inject database instance and its DAO method since we want our database and DAO to be Singleton and live throughout the Application lifecycle.
Next is ActivityModule. All the method inside ActivityComponent
should survive within its injected Activity. Noted that the context used is @ActivityContext
which represent its corresponding activity’s context.
Third is RepositoryModule. All the repository should followed its injected ViewModel’s lifecycle.
Inject into use case
In order to use Hilt, the application must have an Application
class and annotated with @HiltAndroidApp
Then, the Actiivty or Fragment must be annotated with @AndroidEntryPoint
in order to use Hilt injection. After that, we can inject the dependencies that we declared in all the module by using @Inject
For ViewModel, @HiltViewModel
must be used followed by @Inject constructor()` to inject all the dependencies in its constructor.
For Repository, @Inject constructor()
can be used if you wish to use the dependencies from the module.
Conclusion
For me, it helps me a lot in my project as it maintain the Singleton object creation which respect to its lifecycle. So I no need to worry about the variable become null and crash the app with NullPointerException 😱. Since Dagger-Hilt is recently stable release, so I think every Android developer should try it out and embrace the powerful of dependency injection. 😃