匕首刀柄:注释类@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 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章