Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Retention via ViewModel delegation
import android.arch.lifecycle.ViewModel
import android.arch.lifecycle.ViewModelProvider
import android.arch.lifecycle.ViewModelStoreOwner
import kotlin.reflect.KProperty
* This class handles retention of any object using the ViewModel framework. An
* example of this method being used can be found in the Loader Manager framework
* in the Android support library.
class RetentionDelegate<T>(
private val viewModelStoreOwner: ViewModelStoreOwner,
private val initializer: (() -> T)? = null
) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
val (uniqueId, viewModel) = storeInformationFor(property)
// If the value is in the ViewModel, return it
if (viewModel.values.containsKey(uniqueId)) return viewModel.values[uniqueId] as T
// If the viewModel doesn't hold the value and the initialiser is null, we're in an illegal state
initializer ?: throw IllegalStateException("Attempting to invoke getValue when no value is present")
val value = initializer.invoke()
// Add the value to the ViewModel
viewModel.values[uniqueId] = value as Any
return value
* Convenience getter function for viewModel
private fun storeInformationFor(property: KProperty<*>): Pair<String, RetentionViewModel> {
// Get ViewModel
val viewModel = ViewModelProvider(viewModelStoreOwner)[]
// Use the property as a unique ID for the viewModel value map
val uniqueId =
return uniqueId to viewModel
* ViewModel class for holding the values to be retained in the viewModelStore
class RetentionViewModel: ViewModel() {
val values: MutableMap<String, Any> = hashMapOf()
* Extension properties for ease of use
fun <T> Fragment.retained(valInitializer: (() -> T)? = null) = RetentionDelegate(this, valInitializer)
fun <T> AppCompatActivity.retained(valInitializer: (() -> T)? = null) = RetentionDelegate(this, valInitializer)
class RetentionTestActivity: AppCompatActivity() {
val component by retained { instantiateDaggerComponent() }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment