Freelancing for Pale Blue

Looking for flexible work opportunities that fit your schedule?


Hilt: custom entry points

Android Jan 12, 2021

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!

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.