Mark
02/06/2020, 7:36 AMMark
02/06/2020, 7:39 AMarnaud.giuliani
02/06/2020, 8:15 AMMark
02/06/2020, 8:25 AMinit()
before it can be used. Ideally any code that wants to use this singleton would call some suspending equivalent of get()
(or somehow by inject()
) in such a way that init() is called behind the scenes (presumably in some equivalent to single {} that takes a suspending lambda) only when necessary.Mark
02/06/2020, 8:30 AMsingle(named("instanceProvider")) {
suspendableLazy {
createAndInitInstance()
}
}
and then:
private val instanceProvider by lazy {
get<SuspendableProvider<MyClass>>(named("instanceProvider"))
}
suspend fun getInstance(): MyClass? = try {
instanceProvider.get()
} catch (e: Exception) {
Log.e("di", "unable to create instance", e)
null
}
where using some common code:
interface SuspendableProvider<T> {
suspend fun get(): T
val isCompleted: Boolean
}
fun <T> suspendableLazy(provider: suspend () -> T) = object : SuspendableProvider<T> {
private val computed = GlobalScope.async(start = CoroutineStart.LAZY) { provider() }
override val isCompleted: Boolean
get() = computed.isCompleted
override suspend fun get() = computed.await()
}
arnaud.giuliani
02/06/2020, 2:31 PM