Hilt: custom entry points
Hilt is a great dependency injection framework for Android. It has all the strengths of Dagger, delivered in an easy-to-use concise way.
You annotate your Android classes with just an @AndroidEntryPoint
annotation and magically your @Inject
-annotated class members are injected.
The @AndroidEntryPoint
annotation supports injection only for some basic system classes: Activities, Fragments, Views, Services, and BroadcastReceivers. But injection is all magic for you. You never see what injects your system classes. What happens when you encounter a system class (or anything that is not instantiated by you) but you need to inject?
That's what I encounter when migrating to Hilt when I figured out that I needed to inject my Initializer
(from Jetpack's App Startup library) classes. Here's where the custom entry points come into play.
Entry point interface
What would you @Inject
to that class that you don't control? Add an "accessor" method to this @EntryPoint
-annotated interface to get an instance.
@EntryPoint
@InstallIn(SingletonComponent::class)
interface InitializerEntryPoint {
fun myHelper(): MyHelper
}
Just note that you need to "install" this to the same component that the injected instance belongs to. So if you need instances that might be Activity-scoped and Singleton-scoped, you might need more than one entry point interfaces.
Where to add the entry point interface?
According to the official docs, ideally these interfaces should be close to the objects they are used from, rather to the objects they are providing. For instance, in the Jetpack's App Startup Initializer
example, these interfaces should be defined inside the initializers.
class MyCoolInitializer : Initializer<Unit> {
[...]
@EntryPoint
@InstallIn(SingletonComponent::class)
interface InitializerEntryPoint {
fun myHelper(): MyHelper
}
}
This is for making it obvious that these entry point interfaces exists only for these special-case classes that cannot be @Inject
-ed. All other cases should use standard @Inject
and @AndroidEntryPoint
annotations.
How to use them
Finally, to use those Entry Point interfaces, use a static Hilt method and access those "accessor" methods to get your instance!
val myHelper = EntryPoints.get(applicationContext, InitializerEntryPoint::class.java).myHelper()
Happy coding!