带参数的单身人士在Kotlin

我正在尝试将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 } } } 

我错过了什么? 线程安全? 懒惰?

有几个类似的问题,但我不喜欢的答案:)

下面是Google的架构组件示例代码的简洁选择,它使用了alsofunction:

 class UsersDatabase : RoomDatabase() { companion object { @Volatile private var INSTANCE: UsersDatabase? = null fun getInstance(context: Context): UsersDatabase = INSTANCE ?: synchronized(this) { INSTANCE ?: buildDatabase(context).also { INSTANCE = it } } private fun buildDatabase(context: Context) = Room.databaseBuilder(context.applicationContext, UsersDatabase::class.java, "Sample.db") .build() } } 

我不完全确定你为什么需要这样的代码,但这里是我最好的一面:

 class TasksLocalDataSource private constructor(context: Context) : TasksDataSource { private val mDbHelper = TasksDbHelper(context) companion object { private var instance : TasksLocalDataSource? = null fun getInstance(context: Context): TasksLocalDataSource { if (instance == null) // NOT thread safe! instance = TasksLocalDataSource(context) return instance!! } } } 

这与您所写的内容相似,并且具有相同的API。

一些注意事项:

  • 不要在这里使用lateinit 。 它有一个不同的目的,这里是一个可以为空的variables。

  • checkNotNull(context)做什么的? context从来不是空的,这是Kotlin保证的。 所有检查和断言已经由编译器执行。

更新:

如果你所需要的只是一个懒惰的初始化的TasksLocalDataSource实例,那么只需要使用一堆懒惰的属性(在一个对象内或者在包级别上):

 val context = .... val dataSource by lazy { TasksLocalDataSource(context) } 
 Singletons 

单身经常被用来创建它们的简单方法。 而不是通常的静态实例,getInstance()方法和一个私有构造函数,Kotlin使用对象表示法。 为了一致性,对象符号也被用来定义静态方法。

  object CommonApiConfig { private var commonApiConfig: CommonApiConfig? = null fun getInstance(): CommonApiConfig { if (null == commonApiConfig) { commonApiConfig = CommonApiConfig } return CommonApiConfig.commonApiConfig!! } }