I\'m trying to use Room as singleton so I didn\'t have to invoke Room.databaseBuilder()
-which is expensive- more than once.
@Database(entities = ar
I found a solution so here is the answer for future me and any one who might have the same problem.
After some research, I found that I have two options.
so I considered implementing one of them, but this doesn't feel right in kotlin too much boilerplate code :p
so after more research, I stumbled upon this great article which provides an excellent solution which uses Double-checked locking but in an eligant way.
my code becomes like this:
companion object : SingletonHolder({
Room.databaseBuilder(it.applicationContext, AppDatabase::class.java, "train.db").build()
})
from the article:
A reusable Kotlin implementation:
We can encapsulate the logic to lazily create and initialize a singleton with argument inside a
SingletonHolder
class. In order to make that logic thread-safe, we need to implement a synchronized algorithm and the most efficient one — which is also the hardest to get right — is the double-checked locking algorithm.
open class SingletonHolder(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile private var instance: T? = null
fun getInstance(arg: A): T {
val i = instance
if (i != null) {
return i
}
return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(arg)
instance = created
creator = null
created
}
}
}
}
Extra: if you want Singleton with two arguments
open class SingletonHolder2(creator: (A, B) -> T) {
private var creator: ((A, B) -> T)? = creator
@Volatile private var instance: T? = null
fun getInstance(arg0: A, arg1: B): T {
val i = instance
if (i != null) return i
return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(arg0, arg1)
instance = created
creator = null
created
}
}
}
}