Last active
August 12, 2019 22:12
-
-
Save jamiesanson/350910d5f4eba3e909ed99cc96741556 to your computer and use it in GitHub Desktop.
Retention via ViewModel delegation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.arch.lifecycle.ViewModel | |
import android.arch.lifecycle.ViewModelProvider | |
import android.arch.lifecycle.ViewModelStoreOwner | |
import android.support.v4.app.Fragment | |
import android.support.v7.app.AppCompatActivity | |
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 | |
@Suppress("UNCHECKED_CAST") | |
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)[RetentionViewModel::class.java] | |
// Use the property as a unique ID for the viewModel value map | |
val uniqueId = property.name | |
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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