androidx.lifecycle.viewmodel.compose

Objects

LocalViewModelStoreOwner

The CompositionLocal containing the current ViewModelStoreOwner.

Cmn

Annotations

Composables

rememberViewModelStoreOwner

Remembers a ViewModelStoreOwner scoped to the current composable using an existing provider.

Cmn
rememberViewModelStoreProvider

Remembers a new ViewModelStoreProvider which creates a ViewModel scope linked to a parent found in the composition.

Cmn
viewModel

Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or an activity)

Cmn
android

Extension functions summary

PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>>
@SavedStateHandleSaveableApi
<T : Any> SavedStateHandle.saveable(saver: Saver<T, Any>, init: () -> T)

Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via androidx.compose.runtime.saveable.rememberSaveable with a custom Saver can also be saved with SavedStateHandle.

Cmn
PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>>
@SavedStateHandleSaveableApi
<T : Any?, M : MutableState<T>> SavedStateHandle.saveable(
    stateSaver: Saver<T, Any>,
    init: () -> M
)

Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via androidx.compose.runtime.saveable.rememberSaveable with a custom Saver can also be saved with SavedStateHandle.

Cmn
T
@SavedStateHandleSaveableApi
<T : Any> SavedStateHandle.saveable(
    key: String,
    saver: Saver<T, Any>,
    init: () -> T
)

Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via androidx.compose.runtime.saveable.rememberSaveable with a custom Saver can also be saved with SavedStateHandle.

Cmn
MutableState<T>
@SavedStateHandleSaveableApi
<T : Any?> SavedStateHandle.saveable(
    key: String,
    stateSaver: Saver<T, Any>,
    init: () -> MutableState<T>
)

Inter-opt between SavedStateHandle and Saver so that any state holder that is being saved via androidx.compose.runtime.saveable.rememberSaveable with a custom Saver can also be saved with SavedStateHandle.

Cmn

Top-level properties summary

HostDefaultKey<ViewModelStoreOwner?>

A HostDefaultKey used to retrieve the ViewModelStoreOwner provided by the current hosting environment.

Cmn
android
N

Extension functions

SavedStateHandle.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 androidx.compose.runtime.saveable.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))
    }
}

SavedStateHandle.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 androidx.compose.runtime.saveable.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))
    }
}

SavedStateHandle.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 androidx.compose.runtime.saveable.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))
    }
}

SavedStateHandle.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 androidx.compose.runtime.saveable.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))
    }
}

Top-level properties

ViewModelStoreOwnerHostDefaultKey

val ViewModelStoreOwnerHostDefaultKeyHostDefaultKey<ViewModelStoreOwner?>

A HostDefaultKey used to retrieve the ViewModelStoreOwner provided by the current hosting environment.

This key allows the composition to access the host's ViewModelStoreOwner through a decoupled mechanism, typically used by compositionLocalWithHostDefaultOf.

On platforms where a ViewModelStoreOwner is not present or supported, this may resolve to null.