Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android HILT SingletonComponent vs the GoF Singleton instance design pattern

In an Android project, there is a facade implemented as the singleton. I thought it is an better idea converting it to DI with HILT SingletonComponent.

@Module
@InstallIn(SingletonComponent::class)
object MyManagerModule {
    @Provides
    fun provide(@ApplicationContext context: Context): MyManager {
        return MyManager(context)
    }
}

class MyManager @Inject constructor(@ApplicationContext private val ctx: Context){
    //
}

From a few callers, I get the instance of the above MyManager using HILT field injection, i.e.,

@AndroidEntryPoint
class MyCallerFragment : Fragment() {
    @Inject lateinit var myManager: MyManager
// ...

In the debugger, I observed the DI instances are actually NOT the same instance (assuming these fragments are in the same activity lifecycle). I think I must have misunderstand the Hilt DI :-( and would love to hear any explanation if you see my blindspots.

like image 796
Sean Avatar asked Mar 25 '26 21:03

Sean


1 Answers

TL;DR

You need to use the annotation @Singleton. This will tell Hilt to use the same instance of MyManager throughout your app.

Scope of Bindings

According to the documentation:

By default, all bindings in Hilt are unscoped. This means that each time your app requests the binding, Hilt creates a new instance of the needed type.

and

However, Hilt also allows a binding to be scoped to a particular component. Hilt only creates a scoped binding once per instance of the component that the binding is scoped to, and all requests for that binding share the same instance.

The @Singleton annotation scopes your Hilt binding to the application component. (including all children, which are all components) So Hilt will inject the same instance of your object throughout your entire app.

There is an example in this guide by Google.

The @InstallIn annotation

The annotation @InstallIn() tells Hilt in which component MyManager objects will be injected. In your case of @InstallIn(SingletonComponent::class), Hilt will make MyManager available for injection in the application component and all children of this component, which doesn't mean that Hilt will supply the same instance though. Since any default component is a child of the application component, MyManager is currently accessible for injection in any component. (according to the documentation)

like image 114
TomS Avatar answered Mar 27 '26 09:03

TomS