androidx.lifecycle.viewmodel.compose
Objects
LocalViewModelStoreOwner |
The CompositionLocal containing the current |
Cmn
|
Annotations
SavedStateHandleSaveableApi |
android
|
Top-level functions summary
inline VM |
@ComposableReturns an existing |
Cmn
|
inline VM |
@ComposableReturns an existing |
Cmn
|
VM |
@ComposableReturns an existing |
android
|
VM |
@ComposableReturns an existing |
Cmn
|
Extension functions summary
PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> |
@SavedStateHandleSaveableApiInter-opt between |
android
|
PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>> |
@SavedStateHandleSaveableApiInter-opt between |
android
|
T |
@SavedStateHandleSaveableApiInter-opt between |
android
|
MutableState<T> |
@SavedStateHandleSaveableApiInter-opt between |
android
|
Top-level functions
viewModel
@Composable
inline fun <VM : ViewModel> viewModel(
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) { "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" },
key: String? = null,
noinline initializer: CreationExtras.() -> VM
): VM
Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or an activity)
The created ViewModel is associated with the given viewModelStoreOwner and will be retained as long as the scope is alive (e.g. if it is an activity, until it is finished or process is killed).
If the viewModelStoreOwner implements HasDefaultViewModelProviderFactory its default CreationExtras are the ones that will be provided to the receiver scope from the initializer
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.createSavedStateHandle import androidx.lifecycle.viewmodel.CreationExtras import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import androidx.lifecycle.viewmodel.compose.viewModel // Just like any call to viewModel(), the default owner is the LocalViewModelStoreOwner.current. // The lambda is only called the first time the ViewModel needs to be created. val viewModel = viewModel { // Within the lambda, you have direct access to the CreationExtras which allows you to call // extension methods on CreationExtras such as createSavedStateHandle() val handle = createSavedStateHandle() // You can send any custom parameter, repository, etc. to your ViewModel. SavedStateViewModel(handle, "custom_value") } // The handle and parameter are now available from the ViewModel viewModel.handle viewModel.value
| Parameters | |
|---|---|
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
} |
The scope that the created |
key: String? = null |
The key to use to identify the |
noinline initializer: CreationExtras.() -> VM |
lambda used to create an instance of the ViewModel class |
viewModel
@Composable
inline fun <VM : ViewModel> viewModel(
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) { "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" },
key: String? = null,
factory: ViewModelProvider.Factory? = null,
extras: CreationExtras = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) { viewModelStoreOwner.defaultViewModelCreationExtras } else { CreationExtras.Empty }
): VM
Returns an existing ViewModel or creates a new one in the given owner (usually, a fragment or an activity), defaulting to the owner provided by LocalViewModelStoreOwner.
The created ViewModel is associated with the given viewModelStoreOwner and will be retained as long as the owner is alive (e.g. if it is an activity, until it is finished or process is killed).
If default arguments are provided via the CreationExtras, they will be available to the appropriate factory when the ViewModel is created.
import androidx.compose.runtime.remember import androidx.core.os.bundleOf import androidx.lifecycle.DEFAULT_ARGS_KEY import androidx.lifecycle.HasDefaultViewModelProviderFactory import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.CreationExtras import androidx.lifecycle.viewmodel.MutableCreationExtras import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import androidx.lifecycle.viewmodel.compose.viewModel val owner = LocalViewModelStoreOwner.current val defaultExtras = (owner as? HasDefaultViewModelProviderFactory)?.defaultViewModelCreationExtras ?: CreationExtras.Empty // Custom extras should always be added on top of the default extras val extras = MutableCreationExtras(defaultExtras) extras[DEFAULT_ARGS_KEY] = @Suppress("DEPRECATION") // bundleOf is deprecated bundleOf("test" to "my_value") // This factory is normally created separately and passed in val customFactory = remember { object : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { val args = extras[DEFAULT_ARGS_KEY]?.getString("test") @Suppress("UNCHECKED_CAST") // TestViewModel is a basic ViewModel that sets a String variable return TestViewModel(args) as T } } } // Create a ViewModel using the custom factory passing in the custom extras val viewModel = customFactory.create(TestViewModel::class.java, extras) // The value from the extras is now available in the ViewModel viewModel.args
| Parameters | |
|---|---|
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
} |
The owner of the |
key: String? = null |
The key to use to identify the |
factory: ViewModelProvider.Factory? = null |
The |
extras: CreationExtras = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) {
viewModelStoreOwner.defaultViewModelCreationExtras
} else {
CreationExtras.Empty
} |
The default extras used to create the |
viewModel
@Composable
fun <VM : ViewModel> viewModel(
modelClass: Class<VM>,
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) { "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" },
key: String? = null,
factory: ViewModelProvider.Factory? = null,
extras: CreationExtras = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) { viewModelStoreOwner.defaultViewModelCreationExtras } else { CreationExtras.Empty }
): VM
Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or an activity)
The created ViewModel is associated with the given viewModelStoreOwner and will be retained as long as the scope is alive (e.g. if it is an activity, until it is finished or process is killed).
If default arguments are provided via the CreationExtras, they will be available to the appropriate factory when the ViewModel is created.
import androidx.compose.runtime.remember import androidx.core.os.bundleOf import androidx.lifecycle.DEFAULT_ARGS_KEY import androidx.lifecycle.HasDefaultViewModelProviderFactory import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.CreationExtras import androidx.lifecycle.viewmodel.MutableCreationExtras import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import androidx.lifecycle.viewmodel.compose.viewModel val owner = LocalViewModelStoreOwner.current val defaultExtras = (owner as? HasDefaultViewModelProviderFactory)?.defaultViewModelCreationExtras ?: CreationExtras.Empty // Custom extras should always be added on top of the default extras val extras = MutableCreationExtras(defaultExtras) extras[DEFAULT_ARGS_KEY] = @Suppress("DEPRECATION") // bundleOf is deprecated bundleOf("test" to "my_value") // This factory is normally created separately and passed in val customFactory = remember { object : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { val args = extras[DEFAULT_ARGS_KEY]?.getString("test") @Suppress("UNCHECKED_CAST") // TestViewModel is a basic ViewModel that sets a String variable return TestViewModel(args) as T } } } // Create a ViewModel using the custom factory passing in the custom extras val viewModel = customFactory.create(TestViewModel::class.java, extras) // The value from the extras is now available in the ViewModel viewModel.args
| Parameters | |
|---|---|
modelClass: Class<VM> |
The class of the |
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
} |
The scope that the created |
key: String? = null |
The key to use to identify the |
factory: ViewModelProvider.Factory? = null |
The |
extras: CreationExtras = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) {
viewModelStoreOwner.defaultViewModelCreationExtras
} else {
CreationExtras.Empty
} |
The default extras used to create the |
viewModel
@Composable
fun <VM : ViewModel> viewModel(
modelClass: KClass<VM>,
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) { "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner" },
key: String? = null,
factory: ViewModelProvider.Factory? = null,
extras: CreationExtras = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) { viewModelStoreOwner.defaultViewModelCreationExtras } else { CreationExtras.Empty }
): VM
Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or an activity)
The created ViewModel is associated with the given viewModelStoreOwner and will be retained as long as the scope is alive (e.g. if it is an activity, until it is finished or process is killed).
If default arguments are provided via the CreationExtras, they will be available to the appropriate factory when the ViewModel is created.
import androidx.compose.runtime.remember import androidx.core.os.bundleOf import androidx.lifecycle.DEFAULT_ARGS_KEY import androidx.lifecycle.HasDefaultViewModelProviderFactory import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.CreationExtras import androidx.lifecycle.viewmodel.MutableCreationExtras import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import androidx.lifecycle.viewmodel.compose.viewModel val owner = LocalViewModelStoreOwner.current val defaultExtras = (owner as? HasDefaultViewModelProviderFactory)?.defaultViewModelCreationExtras ?: CreationExtras.Empty // Custom extras should always be added on top of the default extras val extras = MutableCreationExtras(defaultExtras) extras[DEFAULT_ARGS_KEY] = @Suppress("DEPRECATION") // bundleOf is deprecated bundleOf("test" to "my_value") // This factory is normally created separately and passed in val customFactory = remember { object : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { val args = extras[DEFAULT_ARGS_KEY]?.getString("test") @Suppress("UNCHECKED_CAST") // TestViewModel is a basic ViewModel that sets a String variable return TestViewModel(args) as T } } } // Create a ViewModel using the custom factory passing in the custom extras val viewModel = customFactory.create(TestViewModel::class.java, extras) // The value from the extras is now available in the ViewModel viewModel.args
| Parameters | |
|---|---|
modelClass: KClass<VM> |
The class of the |
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
} |
The scope that the created |
key: String? = null |
The key to use to identify the |
factory: ViewModelProvider.Factory? = null |
The |
extras: CreationExtras = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) {
viewModelStoreOwner.defaultViewModelCreationExtras
} else {
CreationExtras.Empty
} |
The default extras used to create the |
Extension functions
saveable
@SavedStateHandleSaveableApi
fun <T : Any> SavedStateHandle.saveable(
saver: Saver<T, Any> = autoSaver(),
init: () -> T
): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>>
Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via rememberSaveable with a custom Saver can also be saved with SavedStateHandle.
The key is automatically retrieved as the name of the property this delegate is being used to create.
The returned state T should be the only way that a value is saved or restored from the SavedStateHandle with the automatic key.
Using the same key again with another SavedStateHandle method is not supported, as values won't cross-set or communicate updates.
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.listSaver import androidx.compose.runtime.toMutableStateList import androidx.compose.runtime.toMutableStateMap import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi import androidx.lifecycle.viewmodel.compose.saveable /** A simple item that is not inherently [Parcelable] */ data class Item(val id: UUID, val value: String) @OptIn(SavedStateHandleSaveableApi::class) class SnapshotStateViewModel(handle: SavedStateHandle) : ViewModel() { /** * A snapshot-backed [MutableList] of a list of items, persisted by the [SavedStateHandle]. * The size of this set must remain small in expectation, since the maximum size of saved * instance state space is limited. */ private val items: MutableList<Item> by handle.saveable( saver = listSaver( save = { it.map { item -> listOf(item.id.toString(), item.value) } }, restore = { it.map { saved -> Item(id = UUID.fromString(saved[0]), value = saved[1]) } .toMutableStateList() }, ) ) { mutableStateListOf() } /** * A snapshot-backed [MutableMap] representing a set of selected item ids, persisted by the * [SavedStateHandle]. A [MutableSet] is approximated by ignoring the keys. The size of this * set must remain small in expectation, since the maximum size of saved instance state * space is limited. */ private val selectedItemIds: MutableMap<UUID, Unit> by handle.saveable( saver = listSaver( save = { it.keys.map(UUID::toString) }, restore = { it.map(UUID::fromString).map { id -> id to Unit }.toMutableStateMap() }, ) ) { mutableStateMapOf() } /** * A snapshot-backed flag representing where selections are enabled, persisted by the * [SavedStateHandle]. */ var areSelectionsEnabled by handle.saveable { mutableStateOf(true) } /** A list of items paired with a selection state. */ val selectedItems: List<Pair<Item, Boolean>> get() = items.map { it to (it.id in selectedItemIds) } /** Updates the selection state for the item with [id] to [selected]. */ fun selectItem(id: UUID, selected: Boolean) { if (selected) { selectedItemIds[id] = Unit } else { selectedItemIds.remove(id) } } /** Adds an item with the given [value]. */ fun addItem(value: String) { items.add(Item(UUID.randomUUID(), value)) } }
saveable
@SavedStateHandleSaveableApi
fun <T : Any?, M : MutableState<T>> SavedStateHandle.saveable(
stateSaver: Saver<T, Any> = autoSaver(),
init: () -> M
): PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>>
Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via rememberSaveable with a custom Saver can also be saved with SavedStateHandle.
The key is automatically retrieved as the name of the property this delegate is being used to create.
The delegated MutableState should be the only way that a value is saved or restored from the SavedStateHandle with the automatic key.
Using the same key again with another SavedStateHandle method is not supported, as values won't cross-set or communicate updates.
Use this overload to allow delegating to a mutable state just like you can with rememberSaveable:
var value by savedStateHandle.saveable { mutableStateOf("initialValue") }
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.listSaver import androidx.compose.runtime.toMutableStateList import androidx.compose.runtime.toMutableStateMap import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi import androidx.lifecycle.viewmodel.compose.saveable /** A simple item that is not inherently [Parcelable] */ data class Item(val id: UUID, val value: String) @OptIn(SavedStateHandleSaveableApi::class) class SnapshotStateViewModel(handle: SavedStateHandle) : ViewModel() { /** * A snapshot-backed [MutableList] of a list of items, persisted by the [SavedStateHandle]. * The size of this set must remain small in expectation, since the maximum size of saved * instance state space is limited. */ private val items: MutableList<Item> by handle.saveable( saver = listSaver( save = { it.map { item -> listOf(item.id.toString(), item.value) } }, restore = { it.map { saved -> Item(id = UUID.fromString(saved[0]), value = saved[1]) } .toMutableStateList() }, ) ) { mutableStateListOf() } /** * A snapshot-backed [MutableMap] representing a set of selected item ids, persisted by the * [SavedStateHandle]. A [MutableSet] is approximated by ignoring the keys. The size of this * set must remain small in expectation, since the maximum size of saved instance state * space is limited. */ private val selectedItemIds: MutableMap<UUID, Unit> by handle.saveable( saver = listSaver( save = { it.keys.map(UUID::toString) }, restore = { it.map(UUID::fromString).map { id -> id to Unit }.toMutableStateMap() }, ) ) { mutableStateMapOf() } /** * A snapshot-backed flag representing where selections are enabled, persisted by the * [SavedStateHandle]. */ var areSelectionsEnabled by handle.saveable { mutableStateOf(true) } /** A list of items paired with a selection state. */ val selectedItems: List<Pair<Item, Boolean>> get() = items.map { it to (it.id in selectedItemIds) } /** Updates the selection state for the item with [id] to [selected]. */ fun selectItem(id: UUID, selected: Boolean) { if (selected) { selectedItemIds[id] = Unit } else { selectedItemIds.remove(id) } } /** Adds an item with the given [value]. */ fun addItem(value: String) { items.add(Item(UUID.randomUUID(), value)) } }
saveable
@SavedStateHandleSaveableApi
fun <T : Any> SavedStateHandle.saveable(
key: String,
saver: Saver<T, Any> = autoSaver(),
init: () -> T
): T
Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via rememberSaveable with a custom Saver can also be saved with SavedStateHandle.
The returned state T should be the only way that a value is saved or restored from the SavedStateHandle with the given key.
Using the same key again with another SavedStateHandle method is not supported, as values won't cross-set or communicate updates.
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.listSaver import androidx.compose.runtime.toMutableStateList import androidx.compose.runtime.toMutableStateMap import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi import androidx.lifecycle.viewmodel.compose.saveable /** A simple item that is not inherently [Parcelable] */ data class Item(val id: UUID, val value: String) @OptIn(SavedStateHandleSaveableApi::class) class SnapshotStateViewModel(handle: SavedStateHandle) : ViewModel() { /** * A snapshot-backed [MutableList] of a list of items, persisted by the [SavedStateHandle]. * The size of this set must remain small in expectation, since the maximum size of saved * instance state space is limited. */ private val items: MutableList<Item> = handle.saveable( key = "items", saver = listSaver( save = { it.map { item -> listOf(item.id.toString(), item.value) } }, restore = { it.map { saved -> Item(id = UUID.fromString(saved[0]), value = saved[1]) } .toMutableStateList() }, ), ) { mutableStateListOf() } /** * A snapshot-backed [MutableMap] representing a set of selected item ids, persisted by the * [SavedStateHandle]. A [MutableSet] is approximated by ignoring the keys. The size of this * set must remain small in expectation, since the maximum size of saved instance state * space is limited. */ private val selectedItemIds: MutableMap<UUID, Unit> = handle.saveable( key = "selectedItemIds", saver = listSaver( save = { it.keys.map(UUID::toString) }, restore = { it.map(UUID::fromString).map { id -> id to Unit }.toMutableStateMap() }, ), ) { mutableStateMapOf() } /** * A snapshot-backed flag representing where selections are enabled, persisted by the * [SavedStateHandle]. */ var areSelectionsEnabled by handle.saveable("areSelectionsEnabled") { mutableStateOf(true) } /** A list of items paired with a selection state. */ val selectedItems: List<Pair<Item, Boolean>> get() = items.map { it to (it.id in selectedItemIds) } /** Updates the selection state for the item with [id] to [selected]. */ fun selectItem(id: UUID, selected: Boolean) { if (selected) { selectedItemIds[id] = Unit } else { selectedItemIds.remove(id) } } /** Adds an item with the given [value]. */ fun addItem(value: String) { items.add(Item(UUID.randomUUID(), value)) } }
saveable
@SavedStateHandleSaveableApi
fun <T : Any?> SavedStateHandle.saveable(
key: String,
stateSaver: Saver<T, Any>,
init: () -> MutableState<T>
): MutableState<T>
Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via rememberSaveable with a custom Saver can also be saved with SavedStateHandle.
The returned MutableState should be the only way that a value is saved or restored from the SavedStateHandle with the given key.
Using the same key again with another SavedStateHandle method is not supported, as values won't cross-set or communicate updates.
Use this overload if you remember a mutable state with a type which can't be stored in the Bundle so you have to provide a custom saver object.
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.listSaver import androidx.compose.runtime.toMutableStateList import androidx.compose.runtime.toMutableStateMap import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi import androidx.lifecycle.viewmodel.compose.saveable /** A simple item that is not inherently [Parcelable] */ data class Item(val id: UUID, val value: String) @OptIn(SavedStateHandleSaveableApi::class) class SnapshotStateViewModel(handle: SavedStateHandle) : ViewModel() { /** * A snapshot-backed [MutableList] of a list of items, persisted by the [SavedStateHandle]. * The size of this set must remain small in expectation, since the maximum size of saved * instance state space is limited. */ private val items: MutableList<Item> = handle.saveable( key = "items", saver = listSaver( save = { it.map { item -> listOf(item.id.toString(), item.value) } }, restore = { it.map { saved -> Item(id = UUID.fromString(saved[0]), value = saved[1]) } .toMutableStateList() }, ), ) { mutableStateListOf() } /** * A snapshot-backed [MutableMap] representing a set of selected item ids, persisted by the * [SavedStateHandle]. A [MutableSet] is approximated by ignoring the keys. The size of this * set must remain small in expectation, since the maximum size of saved instance state * space is limited. */ private val selectedItemIds: MutableMap<UUID, Unit> = handle.saveable( key = "selectedItemIds", saver = listSaver( save = { it.keys.map(UUID::toString) }, restore = { it.map(UUID::fromString).map { id -> id to Unit }.toMutableStateMap() }, ), ) { mutableStateMapOf() } /** * A snapshot-backed flag representing where selections are enabled, persisted by the * [SavedStateHandle]. */ var areSelectionsEnabled by handle.saveable("areSelectionsEnabled") { mutableStateOf(true) } /** A list of items paired with a selection state. */ val selectedItems: List<Pair<Item, Boolean>> get() = items.map { it to (it.id in selectedItemIds) } /** Updates the selection state for the item with [id] to [selected]. */ fun selectItem(id: UUID, selected: Boolean) { if (selected) { selectedItemIds[id] = Unit } else { selectedItemIds.remove(id) } } /** Adds an item with the given [value]. */ fun addItem(value: String) { items.add(Item(UUID.randomUUID(), value)) } }