Singleton 类应该使用什么?来自 Dagger 的真正的 Singleton 或 @Singleton 注释?

Gro*_*oot 3 android kotlin dagger dagger-hilt

我正在学习使用 Hilt 和 Dagger 进行依赖注入,我想知道...当使用 Singleton 模式创建类时,我应该使用真正的 Singleton 还是 Hilt 注释?我在互联网上搜索,但找不到显示差异的结论性解决方案,而且当我单击从 Hilt 打开生成的文件时,它看起来不像单例,它是“threadissuesproof”吗?

“真正的单例”,像这样:

class SongController private constructor() {
companion object {
    @Volatile
    private var INSTANCE: SongController? = null

    fun getInstance(): SongController {
        synchronized(this) {
            var instance = INSTANCE
            if (instance == null) {
                instance = SongController()
                INSTANCE = instance
            }
            return instance
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

或者 Hilt 的 @Singleton 注释?

@Singleton
class SongController @Inject constructor() {}
Run Code Online (Sandbox Code Playgroud)

使用注释有什么好处吗?最好、最安全的选择仍然是 getInstace() ->synchronized() 块?

在这种情况下我应该使用哪一个?

我不明白的最重要的问题是,注释的行为方式是否相同?

Ten*_*r04 5

在大多数情况下,您应该更喜欢单例的 DI 框架版本。它并不完全相同,但实际上,对于使用 DI 来设置所有内容的应用程序来说,只有一个实例。这比传统的单例更受欢迎,因为它允许您交换备用版本进行测试。

关于评论:object绝对不包括依赖构造函数属性的单例的情况。

顺便说一句,您的传统单例代码可以改进为使用双重检查锁定,以避免必须永远同步每次访问。实际上,就您现在的代码而言,不需要 Volatile,但您确实需要它来进行双重检查锁定。这是一个例子:

class SongController private constructor(someParameter: SomeType) {
companion object {
    @Volatile
    private var INSTANCE: SongController? = null

    fun getInstance(someParameter: SomeType): SongController = INSTANCE ?: synchronized(this) {
            INSTANCE ?: SongController(someParameter).also { INSTANCE = it }
        }
}
}
Run Code Online (Sandbox Code Playgroud)