Skip to content

Instantly share code, notes, and snippets.

@mrmitew
Last active September 12, 2018 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrmitew/de8527daaa2c7e92122898fd85e7b6ba to your computer and use it in GitHub Desktop.
Save mrmitew/de8527daaa2c7e92122898fd85e7b6ba to your computer and use it in GitHub Desktop.
Using kotlin's features to inject values that are suspend computed into any class constructor
import android.os.Looper
import kotlinx.coroutines.experimental.*
import kotlin.system.measureTimeMillis
abstract class SuspendClassInitializer<out T> constructor(
private val initDispatcher: CoroutineDispatcher,
instanceFactory: () -> T
) {
private val delegate = lazy(instanceFactory)
private val instance by delegate
constructor(instanceFactory: () -> T) : this(Dispatchers.Default, instanceFactory)
suspend operator fun invoke(): T {
return if (delegate.isInitialized()) instance else withContext(initDispatcher) {
check(Thread.currentThread() != Looper.getMainLooper().thread)
instance
}
}
}
class HeavyClass private constructor() {
companion object : SuspendClassInitializer<HeavyClass>(::HeavyClass)
var data: Int = -1
init {
// Artificially blocking the initialization of the class
runBlocking {
println("Initializing something heavy..")
delay(3000)
data = 42
println("Finally, it is initialized!")
}
}
}
fun example() {
println("Will init the heavy class")
GlobalScope.launch {
val t = measureTimeMillis {
val heavyClass = HeavyClass()
println("The data is: ${heavyClass.data}")
}
println("It took ${t}ms to init the heavy class")
}
println("Do something else here")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment