Skip to content

Instantly share code, notes, and snippets.

@whalemare
Created June 21, 2019 08:50
Show Gist options
  • Save whalemare/527d4c56b2589acb9e5739419709b017 to your computer and use it in GitHub Desktop.
Save whalemare/527d4c56b2589acb9e5739419709b017 to your computer and use it in GitHub Desktop.
class ProfileFragment : Fragment() {
val viewModel: ProfileViewModel by viewModel()
}
import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.OnLifecycleEvent
import android.support.annotation.RestrictTo
import java.io.Serializable
private object UNINITIALIZED_VALUE
/**
* This was copied from SynchronizedLazyImpl but modified to automatically initialize in ON_CREATE.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
class lifecycleAwareLazy<out T>(private val owner: LifecycleOwner, initializer: () -> T) : Lazy<T>, Serializable {
private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
// final field is required to enable safe publication of constructed instance
private val lock = this
init {
owner.lifecycle.addObserver(object: LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onStart() {
if (!isInitialized()) value
owner.lifecycle.removeObserver(this)
}
})
}
@Suppress("LocalVariableName")
override val value: T
get() {
val _v1 = _value
if (_v1 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return _v1 as T
}
return synchronized(lock) {
val _v2 = _value
if (_v2 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST") (_v2 as T)
}
else {
val typedValue = initializer!!()
_value = typedValue
initializer = null
typedValue
}
}
}
override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."
}
/**
* Inject [viewModelClass] and setup it in [Fragment.onCreate]
*/
inline fun <T, reified VM : ViewModel> T.viewModel(
viewModelClass: KClass<VM> = VM::class
) where T : Fragment = lifecycleAwareLazy(this) {
return@lifecycleAwareLazy ViewModelProviders.of(this).get(VM::class.java)
}
/**
* Inject [viewModelClass] and setup it in [FragmentActivity.onCreate]
*/
inline fun <T, reified VM : ViewModel> T.viewModel(
viewModelClass: KClass<VM> = VM::class
) where T : FragmentActivity = lifecycleAwareLazy(this) {
return@lifecycleAwareLazy ViewModelProviders.of(this).get(VM::class.java)
}
/**
* Inject [viewModelClass] and setup it in [FragmentActivity.onCreate]
*/
inline fun <T, reified VM : ViewModel> T.sharedViewModel(
viewModelClass: KClass<VM> = VM::class
) where T : Fragment = lifecycleAwareLazy(this) {
return@lifecycleAwareLazy ViewModelProviders.of(this.activity!!).get(VM::class.java)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment