匕首刀柄:注释类@Singleton 和提供函数@Singleton 之间的区别

Posted

技术标签:

【中文标题】匕首刀柄:注释类@Singleton 和提供函数@Singleton 之间的区别【英文标题】:Dagger hilt: Difference between annotating a class @Singleton and a provides function @Singleton 【发布时间】:2021-10-22 04:30:50 【问题描述】:

我的问题非常简单明了:这两个注释/示例有什么区别:

示例一

@Singleton
class MySingletonClass() 

@Module
@InstallIn(FragmentComponent::class)
abstract class MyFragmentModule 
   @Provides
   fun provideMySingletonClass() = MySingletonClass()

示例二

class MySingletonClass() 

@Module
@InstallIn(FragmentComponent::class)
abstract class MyFragmentModule 

   @Singleton
   @Provides
   fun provideMySingletonClass() = MySingletonClass()

我知道的唯一区别是,第二个示例给了我以下错误:

error: [Dagger/IncompatiblyScopedBindings] FragmentC scoped with @dagger.hilt.android.scopes.FragmentScoped may not reference bindings with different scopes:

这是否意味着示例一中的@Singleton 注释被简单地忽略了?

【问题讨论】:

您的***组件很可能带有@Singleton 注释,这意味着MySingletonClass 可以与该组件一起使用。您不能在组件/子组件中具有混合范围,依赖项要么与组件/子组件具有相同的范围,要么是无范围的。在这种情况下,无论您在哪里使用MySingletonClass,它都将是依赖图中的同一个实例,但不要混淆,因为这个类不是真正的“单例”,它只是意味着它在这个依赖图的上下文中是一个共享实例. @Singleton 只是库附带的范围名称。 @MarkKeen 那么这是否意味着在我的示例中,@Singleton 被简单地忽略并且不是“真正的”单身 我在解释错误,这与您的问题完全不同 - 您提出问题的理由并不真正符合错误。正如在下面的答案中指出的那样,您在 MySingletonClass 类上错过了 @Inject,因此 Dagger 看不到它。但是,如果您添加 @Inject 注释,您将收到相同的错误,直到您从片段模块中删除 @Singleton @Provides fun provideMySingletonClass() = MySingletonClass()。我在上面的评论中解释了它的语义。 【参考方案1】:

在示例一中,您的 @Singleton 注释被忽略,但这仅仅是因为您在 @Provides 方法中自己调用了构造函数。因为 Dagger 不与您的 MySingletonClass 构造函数交互,所以它无法读取或使用注解。

如果你的@Singleton class MySingletonClass 有一个@Inject constructor——即使是一个空的——那么 Dagger 就可以直接与之交互只要你也删除了@Provides fun,这将覆盖构造函数检测。完成此操作后,@Singleton 的行为在任一语法中都是相同的。


关于错误消息“错误:[Dagger/IncompatiblyScopedBindings] XXX 作用域为@YYY 可能不会引用具有不同作用域的绑定”:@Andrew 这里真正的问题是,在示例二中,你是尝试在您安装在 FragmentComponent 中的模块中声明 @Singleton 绑定。 @Singleton 绑定只能发生在@Singleton 组件which in Hilt is SingletonComponent 中。我不记得了,但我认为您的示例一(带有我描述的编辑)将适用于单例行为并且不会出现错误,因为 Dagger 会自动选择层次结构中的适当组件来安装您的 MySingletonClass。

【讨论】:

为什么我不能创建片段依赖@Singleton? @FragmentScoped 这里是替代方案吗? @Andrew 这里真正的问题是,在示例二中,您试图在安装在 FragmentComponent 中的模块中声明 @Singleton 绑定。 @Singleton 绑定只能发生在@Singleton 组件which in Hilt is SingletonComponent 中。我不记得了,但我认为您的示例一(带有我描述的编辑)将适用于单例行为并且不会出现错误,因为 Dagger 会自动在层次结构中选择适当的组件来安装您的 MySingletonClass @Andrew 如果您想在整个应用程序中使用一个实例,请在SingletonComponent 中使用@Singleton 绑定,或者如果您希望每个片段一个实例,请在FragmentComponent 中使用FragmentScoped 绑定。无论哪种方式,都可以在 FragmentComponent 中访问绑定。

以上是关于匕首刀柄:注释类@Singleton 和提供函数@Singleton 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

无法提供匕首改装

Kotlin 中的“宁愿在该类上运行匕首处理器”

模块化车刀柄为什么可以解决车削加工中刀尖崩损导致刀柄损坏等问题

Singleton 单例模式

Singleton单例模式

单例模式(Singleton Pattern)