Android HILT SingletonComponent 与 GoF Singleton 实例设计模式

Sea*_*ean 10 android dagger-hilt

在 Android 项目中,有一个外观作为单例实现。我认为使用 HILT SingletonComponent 将其转换为 DI 是一个更好的主意。

@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){
    //
}
Run Code Online (Sandbox Code Playgroud)

从几个调用者那里,我使用 HILT 字段注入获取了上述 MyManager 的实例,即

@AndroidEntryPoint
class MyCallerFragment : Fragment() {
    @Inject lateinit var myManager: MyManager
// ...
Run Code Online (Sandbox Code Playgroud)

在调试器中,我观察到 DI 实例实际上不是一个实例(假设这些片段处于相同的活动生命周期中)。我想我一定是误解了 Hilt DI :-( 如果你看到我的盲点,我很想听听任何解释。

小智 18

长话短说

您需要使用注释@Singleton。这将告诉 Hilt 在整个应用程序中使用相同的 MyManager 实例。

绑定范围

根据文档

默认情况下,Hilt 中的所有绑定都是无作用域的。这意味着每次您的应用程序请求绑定时,Hilt 都会创建所需类型的新实例。

然而,Hilt 还允许将绑定限定在特定组件的范围内。Hilt 只为绑定范围内的组件的每个实例创建一次范围绑定,并且对该绑定的所有请求共享同一个实例。

@Singleton注释将您的 Hilt 绑定范围限定到应用程序组件。(包括所有子项,它们都是组件)因此 Hilt 将在整个应用程序中注入对象的相同实例。

Google 的本指南中有一个示例。

注释@InstallIn

该注释@InstallIn()告诉 Hilt MyManager 对象将被注入到哪个组件中。在您的情况下@InstallIn(SingletonComponent::class),Hilt 将使 MyManager 可用于在应用程序组件和该组件的所有子组件中进行注入,但这并不意味着 Hilt 将提供相同的实例。由于任何默认组件都是应用程序组件的子组件,因此目前可以在任何组件中访问 MyManager 进行注入。(根据文档