Migrating Tokopedia Academy App From Dagger Android Into Hilt!
Everyone who has ever used Dagger might be confusing in the beginning, or maybe in some period. Dagger’s rule is also quite stringent. For me, Dagger has a high learning curve. We need Component
, Module
, and have to Inject
in a specific class. Then Google hears our pain with inventing Hilt to make Dagger more fun and straightforward. More about superpower and advantage of Hilt can be found here.
Hilt is a dependency injection library built on top of Dagger, so it has all ability from Dagger, such as compile-time correctness, runtime performance, scalability, and Android Studio support that Dagger provides. I already tried Hilt once, and this is amazing and simple; it reduces even much code in the simple sample project below.
In this article, I will convert Tokopedia Academy Movie App project from Dagger Android to Hilt. Before starting, to clarify the context me with other team members have been created a Movie App project for Tokopedia Academy, which was held before. In general, this academy has the objective of conveying Tokopedia Android Technology in a fundamentally.
Getting started with Hilt
First, add Hilt plugin in build.gradle
root project.
buildscript {
...
dependencies {
...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
}
}
Then, add Hilt dependencies in your build.gradle
application level. Also, don’t forget to enable Java 8, since Hilt uses Java 8.
...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'
android {
...
}
dependencies {
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}
Migrating Application
Below is the Application
class using Dagger Android, We need to override DaggerApplication()
and implement the functions to tell Dagger about Application
.
Below is the Application
with Hilt, pretty neat, right? We even delete all the function and leave it empty. If using Hilt, the app must contain Application
with @HiltAndroidApp
to attach Dagger to the Application
of your apps and code generation.
Hilt also can provide another class to specify and generate component in which class you want to provide, like :
Application
(by using@HiltAndroidApp
)Activity
Fragment
View
Service
BroadcastReceiver
Migrating Inject View
If you’re using Dagger 2 or Dagger Android, your view like Activity/Fragment
will have DaggerComponent.inject
or override DaggerFragment()
code.
In our project We override DaggerFragment()
:
With Hilt, We are free to remove all of this boilerplate into :
From this code We change
DaggerFragment()
intoFragment()
or if you using Dagger 2, just removeYourComponentDaggerModule.inject()
Then change into @AndroidEntryPoint
annotation. This annotation behaves like @HiltAndroidApp
in the previous section. *NOTE: If you annotate the Fragment
, you also must annotate Android classes that depend on it. For example, We need to annotate MovieDetailActivity.kt
too.
Migrating Module
Sometimes if you cannot provide constructor-injected. Like in this project, We need Retrofit
instance. But Dagger still doesn’t know how to provide the Retrofit
because Dagger can’t create the Retrofit
object by itself, and Retrofit
is an external library that Dagger doesn’t know. So We need to provide the Retrofit
instance manually inside our @Module
.
With Hilt, module behaves the same as Dagger, but We need one additional annotation @InstallIn()
.@InstallIn(ApplicationComponent::class)
will tell Hilt where the module should be provided and generate components for us. For example, in this snippet code, this code acts to provide Retrofit
in MovieApplication.kt
, so when MovieApplication.kt
is created, the Retrofit
instance also created.
As We said before, Hilt will generate components for us, so what? Ya! Exactly what you thought. We don’t even need our legacy components here, so We remove all of our components!
Another generated component you can use :
Migrating View Model Injector Factory
Last but not least, this project uses ViewModel
, and We think it’s widespread that many new apps use this too. Usually, if we use ViewModel
we need to provide our ViewModel
and ViewModelFactory
with Dagger. This also has a problem with boilerplate code like :
and something like this in your module :
We can delete all of those codes!
Hilt includes extensions for providing classes from other Jetpack
libraries and currently supports the following Jetpack
components:
ViewModel
WorkManager
First, add new dependencies in your app/build.gradle
, and don’t forget to sync gradle.
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0alpha01'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
Then We change @inject
constructor in our ViewModel
into @ViewModelInject
. Here we go, our ViewModel
already injected with Factory.
Conclusion
That’s all the migrating our project from Dagger Android into Hilt. From here, We have s conclusion and pros/cons with Android Hilt.
Pros :
- It’s now super easy to use Dagger with Hilt
- Reduce more codes
- Reduce boilerplate
Jetpack
Integration- It’s easy to migrate, especially if you already have Dagger in your legacy code
Cons :
- Hilt in Dynamic Features need extra components and inject similar with Dagger 2
If you have Dynamic Feature
module, you need an extra component and also need manually inject like Dagger 2 do, like :
class LoginActivity : AppCompatActivity() {
@Inject
lateinit var loginAnalyticsAdapter: LoginAnalyticsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
DaggerLoginComponent.builder()
.context(this)
.appDependencies(
EntryPointsAccessors.fromApplication(
applicationContext,
LoginModuleDependencies::class.java
)
)
.build()
.inject(this)
super.onCreate(savedInstanceState)
...
}
}
Tokopedia Application itself has many Dynamic Feature Modules but several modules still not implemented yet. This can cause inconsistency between modules because if we create a new Dynamic Features module we need to create an extra component and even we need to manual inject in view. We also need to change the existing DF Module to DF Hilt Support. So that’s why we need to gather more data to ensure Hilt fit perfectly with our existing code. Source
2. Custom Scope
and Component
also need more research
Full Project can be found here :
Then here is the PR :
Source :
https://developer.android.com/training/dependency-injection/hilt-jetpack
https://developer.android.com/training/dependency-injection
Deep Dive Here :