In the previous blog post, I shared the guide to use Hilt to implement dependency injection in Android.
But there’s the fact that it’s not many chances for you to use Hilt in a project from the start. In most cases, you’ll have to migrate gradually from the legacy dependency injection library to Hilt. Also, there’s a high chance that dependency injection library is Dagger.
In this post, I’ll share a step-by-step guide to migrate from Dagger to Hilt gradually. Those were my personal experience when I tried to use Hilt in my side project — Buckist.
Buckist - Best Bucket List App - Ứng dụng trên Google Play
Buckist - Best Bucket List App is a powerful app which allows you to create and manage a list of things to do before…
Also, I assume that you already have knowledge of Dagger and basic usage of Hilt.
1. Review the current project
Before doing any migrations, sit back and take an overall look at the current project.
The sample app is pretty simple, with 2 screens:
All the data are mocked, and implementation is simplified to a minimum to save me from laziness and procrastination 🥲.
For the implementation details:
- I apply a simple Clean Architecture approach.
- Use Dagger for dependency injection (of course 😂) with
Also, because the main purpose of this post is migrating from Dagger to Hilt, I’ll visualize the Dagger components and modules relationship of this sample project for easier following:
2. Plan the migration
“A goal without a plan is just a wish.“ (Antoine de Saint-Exupéry)
After reviewing the current situation and before getting your hand dirty, you probably want to have a migration plan first.
What should we plan?
- The component hierarchy equivalent: you must have a crystal clear idea of which component your app will map with which Hilt component.
- The migration journey: which modules/components/activities/fragments should be migrated first or last. This depends on your particular project.
For this demo migration plan, the component hierarchy mapping is pretty straightforward:
AppComponentwill map to
ProfileFragmentModulewill be installed into
Also, for the demo purpose, I’ll migrate the
LoginFragment to Hilt first while keeping Dagger in
ProfileFragment to show you how to gradually migrating to Hilt piece by piece.
3. Migrate AppComponent Dependencies
The goal of this stage is to migrate all dependencies in
SingletonComponent while keeping interop with legacy Dagger implementation everywhere else.
Install all the Modules into SingletonComponent
To do this, put the annotation
@InstallIn(SingletonComponent::class) on top of the module class.
If you have too many modules, you can create an aggregator module that includes all the existing modules for temporary.
Update Application class
Now we can set up Hilt for the application class. Add the
@HiltAndroidApp and remove the
DaggerAppComponent.create().inject(this) inside the
onCreate() and we’re good to go.
As you can see, we still keep the
HasAndroidInjector implementation. Because we want to continue support Dagger while migrating to Hilt gradually.
After finishing the migration, you can go back and remove this code.
Now let’s rebuild the project 🔄
Bam! Android Studio will throw this error right into your face 💥
Basically, Hilt requires all the modules to have the
@InstallIn annotation to be declared.
To skip this fatal warning during the migration, add this line into your
app/build.gradle and remember to remove it after finishing the migration.
Clean then rebuild, and you’re good to go! 🎯
4. Migrate Activities / Fragments
After migrated the
AppComponent dependencies, now you can start gradually migrating
Fragment within the application.
Migrate Activity that uses
Activity that currently use
AndroidInjection, the migration will be pretty straightforward.
- First, add
@InstallIn(ActivityComponent::class)annotation into the
- Remove the
- Add the
@AndroidEntryPointannotation on the top of the
Activityclass and remove the
That’s it! You just finished migrating an
Activity ! 🎉 Easy peasy, right?
Migrate Fragment that uses
The migration for
Fragment is pretty similar to the
- First, add
@InstallIn(FragmentComponent::class)annotation into the
- Then, remove the
- Finally, go to the
Fragmentclass, add the
@AndroidEntryPointannotation on the top and remove
Clean + rebuild, and you’re good to go! 🚀
After finish migrating all the
Fragment of an
Activity , you can finally remove the
5. Migrate ViewModel
ViewModel is much easier.
- Just need to put the
- Remove all the
ViewModelbinding if any:
- Install all the required dependencies into
- Retrieve the
ViewModelinstance when using:
That’s all you need to do for migrating the
6. Migrate classes that use AppComponent for injection
We already covered the basic cases where you can use
AndroidInjection , but there’re also many cases that you use the
Component to inject the dependencies manually. This section will show you how to migrate those cases.
The idea is to replace the
AppComponent injection by the Hilt
- First, create an
EntryPointthat will act as your legacy
EntryPointwill have all the required
inject()and exposed dependencies methods. You can let the
EntryPointimplement the legacy
Componentfor avoiding copy-code during the migration.
- Replace the
- By the new
- Then you can apply injection similar to using the legacy
In this post, I’m trying to share a guide that you can keep both Hilt and Dagger at the same time, make sure that you can migrate your project piece by piece.
Also, this post only cover the basic cases that you commonly found in most of Android projects. For more special cases like multi-modules, custom components,… we need more than a blog post to walk through.
Some small reminders to keep in mind when migrating:
- Migrate piece by piece
- Make sure to clean + build at regular check point to make sure you’re still on track
- Clean up legacy Dagger set up after migrated success
Please feel free to comment or have any feedbacks. Happy coding 💻!