How can I make this singleton simpler in Kotlin?

Multi tool use
Multi tool use
The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


How can I make this singleton simpler in Kotlin?



How can I make this singleton simpler in Kotlin for the Android room database initialization?


@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
}
}
}





I had the same issue few days ago.
– Abner Escócio
13 hours ago





Are you sure that you need an im memory database? It will not be persistent after the app is closed!
– Willi Mentzel
13 hours ago




3 Answers
3



You can use an array literal () instead of arrayOf and you can use the elvis operator for the null check. See here.



arrayOf


@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
}
}
}



Since you need the instance you have to save it somewhere, using a companion object seems like a reasonable solution to me.


companion object



If you somehow don't want to save the intance inside AppDatabase, you can also use an object (which is a singleton in Kotlin).


AppDatabase


object AppDatabaseProvider {
private var INSTANCE: AppDatabase? = null

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

fun destroyInstance() {
INSTANCE = null
}
}



These are both options to deal with static data in Kotlin, but you won't get it much shorter than that.



Maybe it will be any advance, try as follow


@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
}
}
}



Your solution is basically fine as is.



Using an array literal is an option, as it's been pointed out by @Willi Mentzel, it makes your code a bit shorter, if you like how it looks.



However, this code for getting the singleton instance is wrong:


private var INSTANCE: AppDatabase? = null

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



The getInMemoryDatabase function never assigns a value to INSTANCE, meaning it will forever be null, and every time the function is called, the right hand side of the Elvis operator will be evaluated and returned. This means a new instance every time - instead of having a singleton, you're just creating a factory with this code.


getInMemoryDatabase


INSTANCE


null



You could use the Elvis operator to shorten your original code a bit:


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



This will do an extra assignment of INSTANCE to itself every call after the first one though, and I'd argue that saving those couple lines might not be worth it, as your original code with just a regular null check was easier to read than this is.


INSTANCE





Ups, you are right! I updated my answer, but using !! is not necessary. The builder will never return null (but throw exeptions instead).
– Willi Mentzel
3 mins ago





I also think, you won't get it much shorter as nhaarman also showed: stackoverflow.com/questions/44315778/…
– Willi Mentzel
1 min ago






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

YkF,DsMed734cPffmprm
x8FGLLQ7RWvXYGYMY atj93ZkuMDAAScXZ,n CnaAmpoLYIQyyzfg

Popular posts from this blog

Makefile test if variable is not empty

Visual Studio Code: How to configure includePath for better IntelliSense results

Will Oldham