Skip to content

Instantly share code, notes, and snippets.

@edenman
Created February 24, 2017 01:56
Show Gist options
  • Save edenman/8bf06791295793c83fe7920854de751e to your computer and use it in GitHub Desktop.
Save edenman/8bf06791295793c83fe7920854de751e to your computer and use it in GitHub Desktop.
Kotlin lazy delegate that enforces single-initialization by ensuring callers are on the main thread
package my.package.foo
/**
* This method is just a modification of the kotlin stdlib lazy initializer, which by default uses a
* synchronized block to ensure no double-running of the initializer. Synchronized blocks are not
* particularly fast on Android so we try to avoid them when possible: in all of our cases, the
* lazy property is being accessed on the main thread, so it's easier to just check that we're on
* the main thread as a way to ensure no double-running of the initializer.
*/
fun <T> lazyMainThread(initializer: () -> T): Lazy<T> = LazyMainThreadImpl(initializer)
private object UNINITIALIZED_VALUE
private class LazyMainThreadImpl<out T>(initializer: () -> T) : Lazy<T> {
private var initializer: (() -> T)? = initializer
private var _value: Any? = UNINITIALIZED_VALUE
override val value: T
get() {
checkMainThread() // Make sure this value is only ever accessed from the main thread
val _v1 = _value
if (_v1 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return _v1 as T
}
val typedValue = initializer!!()
_value = typedValue
initializer = null
return typedValue
}
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment