【发布时间】:2017-03-16 20:02:55
【问题描述】:
我正在尝试将 Android 应用从 Java 转换为 Kotlin。应用程序中有一些单例。我为没有构造函数参数的单例使用了伴随对象。还有一个带构造函数参数的单例。
Java 代码:
public class TasksLocalDataSource implements TasksDataSource {
private static TasksLocalDataSource INSTANCE;
private TasksDbHelper mDbHelper;
// Prevent direct instantiation.
private TasksLocalDataSource(@NonNull Context context) {
checkNotNull(context);
mDbHelper = new TasksDbHelper(context);
}
public static TasksLocalDataSource getInstance(@NonNull Context context) {
if (INSTANCE == null) {
INSTANCE = new TasksLocalDataSource(context);
}
return INSTANCE;
}
}
我在 kotlin 中的解决方案:
class TasksLocalDataSource private constructor(context: Context) : TasksDataSource {
private val mDbHelper: TasksDbHelper
init {
checkNotNull(context)
mDbHelper = TasksDbHelper(context)
}
companion object {
lateinit var INSTANCE: TasksLocalDataSource
private val initialized = AtomicBoolean()
fun getInstance(context: Context) : TasksLocalDataSource {
if(initialized.getAndSet(true)) {
INSTANCE = TasksLocalDataSource(context)
}
return INSTANCE
}
}
}
我错过了什么吗?线程安全?懒惰?
有几个类似的问题,但我不喜欢答案:)
【问题讨论】:
-
INSTANCE属性暴露了 public setter 有点尴尬 -
@miensol 是否有任何其他选项可以将参数(上下文)传递给伴随对象?
-
将 Context 实例存储在全局单例对象中(无论是 Java 还是 Kotlin)都会造成内存泄漏:stackoverflow.com/a/11908685/147024
-
@yole 如果它是单例的应用程序上下文,则它不是内存泄漏。
-
@LordRaydenMK 如果您在 Android 中使用 Kotlin,我认为您的代码有 4 项改进。我已经做了一些解释的要点。看看:gist.github.com/gaplo917/f186d5c541fbc0d6f77f9b720ec4694c