如何在Kotlin中简化此单例?

时间:2018-07-30 18:59:20

标签: android kotlin android-room

如何在Kotlin中简化该单例以进行Android房间数据库初始化?

@Database(entities = arrayOf(Book::class, User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {

    abstract fun bookModel() : BookDao
    abstract fun userModel() : UserDao

    companion object {
        private var INSTANCE: AppDatabase? = null

        fun getInMemoryDatabase(context: Context): AppDatabase {
            if (INSTANCE == null) {
                INSTANCE = Room.inMemoryDatabaseBuilder(context.applicationContext, AppDatabase::class.java).build()
            }
            return INSTANCE!!
        }

        fun destroyInstance() {
            INSTANCE = null
        }
    }
}

3 个答案:

答案 0 :(得分:2)

您可以使用数组文字([]而不是arrayOf,并且可以使用elvis运算符进行空检查。参见here

@Database(entities = [Book::class, User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {

    abstract fun bookModel() : BookDao
    abstract fun userModel() : UserDao

    companion object {
        private var INSTANCE: AppDatabase? = null

        fun getInMemoryDatabase(context: Context) { 
            INSTANCE = INSTANCE ?: Room.inMemoryDatabaseBuilder(context.applicationContext, AppDatabase::class.java).build()
            return INSTANCE!!
        }

        fun destroyInstance() {
            INSTANCE = null
        }
    }
}

由于需要实例,因此必须将其保存在某个位置,因此使用companion object对我来说似乎是一个合理的解决方案。

如果您不希望将实例保存在AppDatabase中,也可以使用一个对象(在Kotlin中是单例)。

object AppDatabaseProvider {
    private var INSTANCE: AppDatabase? = null

    fun getInMemoryDatabase(context: Context) {
       // ...
    }

    fun destroyInstance() {
        INSTANCE = null
    }
}

这两个都是在Kotlin中处理静态数据的选项,但是您不会比这更短。

答案 1 :(得分:1)

您的解决方案基本上是可以的。

使用数组文字是一种选择,正如@Willi Mentzel指出的那样,如果您喜欢它的外观,它会使您的代码短一些。

但是,用于获取单例实例的此代码是错误的:

private var INSTANCE: AppDatabase? = null

fun getInMemoryDatabase(context: Context) = INSTANCE ?: Room.inMemoryDatabaseBuilder(context.applicationContext, AppDatabase::class.java).build()

getInMemoryDatabase函数从不为INSTANCE分配值,这意味着它将永远为null,并且每次调用该函数时,右手猫王操作员的侧面将被评估并返回。这意味着每次都会有一个新实例-您只需使用此代码创建一个工厂,而不是拥有一个单例。


可以使用Elvis运算符稍微缩短原始代码:

fun getInMemoryDatabase(context: Context): AppDatabase {
    INSTANCE = INSTANCE ?: Room.inMemoryDatabaseBuilder(context.applicationContext, AppDatabase::class.java).build()
    return INSTANCE!!
}

尽管这样,在第一个调用之后,每次调用都会给它自己额外分配INSTANCE,我认为保存那几行可能不值得,因为您的原始代码只有一个常规的null支票比这更容易阅读。

答案 2 :(得分:0)

也许会有进步,请尝试按照以下步骤

@Database(entities = arrayOf(Book::class, User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {

    abstract fun bookModel() : BookDao
    abstract fun userModel() : UserDao

    companion object {
        private var INSTANCE: AppDatabase? = null

        fun getInMemoryDatabase(context: Context): AppDatabase {
            return INSTANCE :? Room.inMemoryDatabaseBuilder(context, this).build()
        }

        fun destroyInstance() {
            INSTANCE = null
        }
    }
}