
Exploring Hilt and what’s main differences from Dagger-Android
Dagger is one of the most popular and most used libraries for building dependency injection, especially in Android. But the initial cost of learning is high and beginners are difficult to debug and hard to understand what’s going on in the compile time. So here is another powerful DI weapon for beginners and old dagger users: Hilt. In this post, we will look around what’s big differences between dagger-android and Hilt and what’s the benefits bu using Hilt.
Next Post
The Hilt reached alpha but there is no official documentation and explains. so I’ve looked around documentations in the code to rely on, interpretations might also be wrong. It is an alpha, the main implementation might be also will be changed in future releases.
Component
Dagger can create a graph of the dependencies in your project that it can use to find out where it should get those dependencies when they are needed. To make Dagger do this, you need to create an interface and annotate it with
@Component
. Dagger creates a container as you would have done with manual dependency injection.
In Dagger-Android, we have to create a component class with a builder/factory, includes every module and we should inject the application context in the Application class after building our project. Here is the Dagger-Android way to construct a component.
But in Hilt, we don’t need to create a component, include every module, and build for generating DaggerAppComponent class.
That’s all! Just by annotating the @HiltAndroidApp annotation, Hilt will do everything itself. Also, the instance of an App can be injected into other modules by the Hilt. How is this possible?
Hilt provides the ApplicationContextModule by default and it is followed by the whole application’s lifecycle. By annotating the @HiltAndroidApp annotation, an instance of the App will be injected into that module internally. So we don’t need to inject the instance of the application in the App class.
Module and Lifecycle
You can use scope annotations to limit the lifetime of an object to the lifetime of its component. This means that the same instance of a dependency is used every time that type needs to be provided.
In the Dagger-Android, we have to create the scope annotations like ActivityScope, FragmentScope for managing the lifecycle of an object. But Hilt provides the following basic scopes as components.
- Application
- Activity / ActivityRetained
- Fragment
- Service
- View / ViewWithFragment
By attaching @InstallIn annotation to a module, the module will get a limited lifetime belongs to the scope. And the lifecycle is managed by Hilt as components. Here is a simple example of the NetworkModule belongs to ApplicationComponent.
And we can limit by making the lifecycle of objects belongs to other components. Here is another example of RepositoryModule.
I guess the ActivityRetainedComponent means that instances will be retained after onDestroy/recreated from screen rotation.
ContributesAndroidInjector
In Dagger-Android, the ContributesAndroidInjector annotation was introduced for generating Subcomponent related codes automatically and removing boilerplate codes. But at some point, writing the ContributesAndroidInjector annotations is also being boilerplates in our huge project. We have to write tons of scope annotations and android injector annotations.
In Hilt, we don’t need to write those annotations and ActivityModule. Instead, Hilt provides a @AndroidEntryPoint annotation.
By attaching the AndroidEntryPoint annotation, the fields in the MainActivity can be injected instances by Hilt. We don’t need to write AndroidInjection.inject(this) or extending DaggerAppCompatActivity class.
ViewModel
After Google announcing Jetpack ViewModel, we need to inject an instance of the ViewModels to Android components. But there is another problem in injecting ViewModel, which is creating an instance of a ViewModel with arguments in constructor. So we have to implement a global or every ViewModelFactory by each ViewModels and implement ViewModelModule for binding ViewModels.
In Hilt, we don’t have to write the ViewModelFactory and ViewModelModule. Instead, Hilt provides @ViewModelInject annotation and @Assisted annotation for SavedStateHandle. (But the Assisted annotation seems will be replaced to Dagger’s AssistedInject in the future). Here is a simple example of MainViewModel.
Conclusion
In this posting, we explored the main differences between Hilt and Dagger-Android. Hilt cut many boilerplate codes to match its name. Also, Hilt helps to construct easier a DI environment for beginner developers. I made a public repository for helping understand Hilt, you can check it in the below link.
