public final class SavedStateHandle


A handle to saved state passed to ViewModel. Typically, SavedStateViewModelFactory provides this object to the ViewModel constructor.

A key-value map allowing retrieval and storage of values to and from the saved state. These values persist through system-initiated process death and remain available to the recreated instance.

Values can be read via get or observed as a flow via getStateFlow. Values can be written via set or by updating the returned flow via getMutableStateFlow.

Summary

Nested types

public static class SavedStateHandle.Companion

Public constructors

Creates a handle with the empty state.

Creates a handle with the given initial arguments.

Public methods

final void

Clear any SavedStateProvider that was previously set via setSavedStateProvider.

final boolean
final T
@MainThread
<T extends Object> get(@NonNull String key)

Returns a value associated with the given key.

final @NonNull MutableLiveData<@NonNull T>

Returns a LiveData that accesses data associated with the given key.

final @NonNull MutableLiveData<@NonNull T>
@MainThread
<T extends Object> getLiveData(@NonNull String key, @NonNull T initialValue)

Returns a LiveData that accesses data associated with the given key.

final @NonNull MutableStateFlow<@NonNull T>
@MainThread
<T extends Object> getMutableStateFlow(@NonNull String key, @NonNull T initialValue)

Returns a MutableStateFlow that will emit the currently active value associated with the given key.

final @NonNull StateFlow<@NonNull T>
@MainThread
<T extends Object> getStateFlow(@NonNull String key, @NonNull T initialValue)

Returns a StateFlow that will emit the currently active value associated with the given key.

final @NonNull Set<@NonNull String>

Returns all keys contained in this SavedStateHandle

final T
@MainThread
<T extends Object> remove(@NonNull String key)

Removes a value associated with the given key.

final void
@MainThread
<T extends Object> set(@NonNull String key, T value)

Associate the given value with the key.

final void

Sets a SavedStateProvider that will have its state saved into this SavedStateHandle.

Extension functions

final @NonNull ReadWriteProperty<Object, @NonNull T>
<T extends Object> SavedStateHandleDelegateKt.saved(
    @NonNull SavedStateHandle receiver,
    String key,
    @NonNull SavedStateConfiguration configuration,
    @NonNull Function0<@NonNull T> init
)

Returns a property delegate that uses SavedStateHandle to save and restore a value of type T with the default serializer.

final @NonNull ReadWriteProperty<Object, @NonNull T>
<T extends Object> SavedStateHandleDelegateKt.saved(
    @NonNull SavedStateHandle receiver,
    @NonNull KSerializer<@NonNull T> serializer,
    String key,
    @NonNull SavedStateConfiguration configuration,
    @NonNull Function0<@NonNull T> init
)

Returns a property delegate that uses SavedStateHandle to save and restore a value of type T.

final @NonNull T
<T extends Object> SavedStateHandleKt.toRoute(
    @NonNull SavedStateHandle receiver,
    @NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap
)

Returns route as an object of type T

final @NonNull T
<T extends Object> SavedStateHandleKt.toRoute(
    @NonNull SavedStateHandle receiver,
    @NonNull KClass<@NonNull T> route,
    @NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap
)

Returns route as an object of type T

Public constructors

SavedStateHandle

Added in 2.3.0
@VisibleForTesting
public SavedStateHandle()

Creates a handle with the empty state.

Important: This constructor should only be used directly in tests. The created SavedStateHandle is not bound to the current SavedStateRegistryOwner, meaning its internal state will not be restored in the event of a process death.

In production, use viewModelFactory or implement ViewModelProvider.Factory directly, using CreationExtras.createSavedStateHandle to create a SavedStateHandle that is bound with the current SavedStateRegistryOwner.

SavedStateHandle

Added in 2.3.0
@VisibleForTesting
public SavedStateHandle(@NonNull Map<@NonNull StringObject> initialState)

Creates a handle with the given initial arguments.

Important: This constructor should only be used directly in tests. The created SavedStateHandle is not bound to the current SavedStateRegistryOwner, meaning its internal state will not be restored in the event of a process death.

In production, use viewModelFactory or implement ViewModelProvider.Factory directly, using CreationExtras.createSavedStateHandle to create a SavedStateHandle that is bound to the current SavedStateRegistryOwner.

Parameters
@NonNull Map<@NonNull StringObject> initialState

initial arguments for the SavedStateHandle

Public methods

clearSavedStateProvider

Added in 2.3.0
@MainThread
public final void clearSavedStateProvider(@NonNull String key)

Clear any SavedStateProvider that was previously set via setSavedStateProvider.

Note: calling this method within SavedStateProvider.saveState is supported, but will only affect future state saving operations.

Parameters
@NonNull String key

identifier previously used with setSavedStateProvider

contains

Added in 2.3.0
@MainThread
public final boolean contains(@NonNull String key)
Parameters
@NonNull String key

identifier of the value

Returns
boolean

true if a value is associated with key

get

Added in 2.3.0
@MainThread
public final T <T extends Object> get(@NonNull String key)

Returns a value associated with the given key.

Note: If T is an Array of android.os.Parcelable classes, note that you should always use Array<Parcelable> and create a typed array from the result as going through process death and recreation (or using the Don't keep activities developer option) will result in the type information being lost, thus resulting in a ClassCastException if you directly try to assign the result to an Array<CustomParcelable> value.

val typedArray = savedStateHandle.get>("KEY").map { it as CustomParcelable }.toTypedArray()

Parameters
@NonNull String key

identifier of the value

getLiveData

Added in 2.3.0
@MainThread
public final @NonNull MutableLiveData<@NonNull T> <T extends Object> getLiveData(@NonNull String key)

Returns a LiveData that accesses data associated with the given key.

Parameters
@NonNull String key

identifier of the value

See also
getLiveData

getLiveData

Added in 2.3.0
@MainThread
public final @NonNull MutableLiveData<@NonNull T> <T extends Object> getLiveData(@NonNull String key, @NonNull T initialValue)

Returns a LiveData that accesses data associated with the given key.

val liveData = savedStateHandle.getLiveData(KEY, "defaultValue")

Note that LiveData can have null as a valid value. If the initialValue is null and the data does not already exist in the SavedStateHandle, the value of the returned LiveData will be set to null and observers will be notified. You can call getLiveData to avoid dispatching null to observers.

val defaultValue = ... // nullable
val liveData = if (defaultValue != null) {
savedStateHandle.getLiveData(KEY, defaultValue)
} else {
savedStateHandle.getLiveData(KEY)
}

If T is an Array of Parcelable classes, you should always use Array<Parcelable> and create a typed array from the result. Going through process death and recreation (or using the "Don't keep activities" developer option) will result in the type information being lost, causing a ClassCastException if you directly try to observe the result as Array<CustomParcelable>.

val typedArrayLiveData = savedStateHandle.getLiveData<Array<Parcelable>>(
"KEY"
).map { array ->
// Convert the Array<Parcelable> to an Array<CustomParcelable>
array.map { it as CustomParcelable }.toTypedArray()
}
Parameters
@NonNull String key

identifier of the value

@NonNull T initialValue

value to use if no value is associated with key

getMutableStateFlow

Added in 2.9.0
@MainThread
public final @NonNull MutableStateFlow<@NonNull T> <T extends Object> getMutableStateFlow(@NonNull String key, @NonNull T initialValue)

Returns a MutableStateFlow that will emit the currently active value associated with the given key.

val flow = savedStateHandle.getMutableStateFlow(KEY, "defaultValue")

Since this is a MutableStateFlow there will always be a value available which, is why an initial value must be provided. The value of this flow is changed by making a call to set, passing in the key that references this flow or by updating the value of the returned MutableStateFlow

If there is already a value associated with the given key, the initial value will be ignored.

Note 1: If T is an Array of Parcelable classes, note that you should always use Array<Parcelable> and create a typed array from the result as going through process death and recreation (or using the Don't keep activities developer option) will result in the type information being lost, thus resulting in a ClassCastException if you directly try to collect the result as an Array<CustomParcelable>.

val typedArrayFlow = savedStateHandle.getMutableStateFlow>( "KEY" ).map { array -> // Convert the Array to an Array array.map { it as CustomParcelable }.toTypedArray() }

Note 2: On Android, this method is mutually exclusive with getLiveData for the same key. You should use either getMutableStateFlow or getLiveData to access the stored value, but not both. Using both methods with the same key will result in an IllegalStateException.

Parameters
@NonNull String key

identifier of the flow

@NonNull T initialValue

value to use if no value is associated with key

getStateFlow

Added in 2.5.0
@MainThread
public final @NonNull StateFlow<@NonNull T> <T extends Object> getStateFlow(@NonNull String key, @NonNull T initialValue)

Returns a StateFlow that will emit the currently active value associated with the given key.

val flow = savedStateHandle.getStateFlow(KEY, "defaultValue")

Since this is a StateFlow there will always be a value available which, is why an initial value must be provided. The value of this flow is changed by making a call to set, passing in the key that references this flow.

If there is already a value associated with the given key, the initial value will be ignored.

Note: If T is an Array of android.os.Parcelable classes, note that you should always use Array<Parcelable> and create a typed array from the result as going through process death and recreation (or using the Don't keep activities developer option) will result in the type information being lost, thus resulting in a ClassCastException if you directly try to collect the result as an Array<CustomParcelable>.

val typedArrayFlow = savedStateHandle.getStateFlow<Array<Parcelable>>(
"KEY"
).map { array ->
// Convert the Array<Parcelable> to an Array<CustomParcelable>
array.map { it as CustomParcelable }.toTypedArray()
}
Parameters
@NonNull String key

identifier of the flow

@NonNull T initialValue

value to use if no value is associated with key

keys

Added in 2.3.0
@MainThread
public final @NonNull Set<@NonNull Stringkeys()

Returns all keys contained in this SavedStateHandle

Returned set contains all keys: keys used to get LiveData-s, to set SavedStateProviders and keys used in regular set.

remove

Added in 2.3.0
@MainThread
public final T <T extends Object> remove(@NonNull String key)

Removes a value associated with the given key. If there is a androidx.lifecycle.LiveData and/or StateFlow associated with the given key, they will be removed as well.

All changes to LiveData or StateFlow previously returned by SavedStateHandle.getLiveData or getStateFlow won't be reflected in the saved state. Also, that LiveData or StateFlow won't receive any updates about new values associated by the given key.

Parameters
@NonNull String key

identifier of the value

Returns
T

value previously associated with key, or null if none was present

set

Added in 2.3.0
@MainThread
public final void <T extends Object> set(@NonNull String key, T value)

Associate the given value with the key. The value must have a type that could be stored in SavedState

This also sets values for any active androidx.lifecycle.LiveData or StateFlow.

Parameters
@NonNull String key

identifier of the value

T value

value to associate with key

Throws
IllegalArgumentException

value cannot be saved in saved state

setSavedStateProvider

Added in 2.3.0
@MainThread
public final void setSavedStateProvider(
    @NonNull String key,
    @NonNull SavedStateRegistry.SavedStateProvider provider
)

Sets a SavedStateProvider that will have its state saved into this SavedStateHandle. This provides a mechanism to lazily supply the SavedState for the given key.

Calls to get with the same key will return the previously saved state as a SavedState if it exists.

val previousState: SavedState? = savedStateHandle.get("custom_object") if (previousState != null) { // Convert the previousState into your custom object } savedStateHandle.setSavedStateProvider("custom_object") { savedState { // Put your custom object properties into the SavedState } }

Note: Calling this method within SavedStateProvider.saveState is supported, but will only affect future state saving operations.

Parameters
@NonNull String key

identifier of the state

@NonNull SavedStateRegistry.SavedStateProvider provider

SavedStateProvider which will receive a callback to SavedStateProvider.saveState when the state should be saved

Extension functions

SavedStateHandleDelegateKt.saved

public final @NonNull ReadWriteProperty<Object, @NonNull T> <T extends Object> SavedStateHandleDelegateKt.saved(
    @NonNull SavedStateHandle receiver,
    String key,
    @NonNull SavedStateConfiguration configuration,
    @NonNull Function0<@NonNull T> init
)

Returns a property delegate that uses SavedStateHandle to save and restore a value of type T with the default serializer.

import androidx.lifecycle.serialization.saved

@Serializable data class User(val id: Int, val name: String)
class ProfileViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    val user by savedStateHandle.saved(key = "bar") { User(123, "foo") }
}
Parameters
String key

An optional String key to use for storing the value in the SavedStateHandle. A default key will be generated if it's omitted or when 'null' is passed.

@NonNull SavedStateConfiguration configuration

The SavedStateConfiguration to use. Defaults to SavedStateConfiguration.DEFAULT.

@NonNull Function0<@NonNull T> init

The function to provide the initial value of the property.

Returns
@NonNull ReadWriteProperty<Object, @NonNull T>

A property delegate that manages the saving and restoring of the value.

SavedStateHandleDelegateKt.saved

public final @NonNull ReadWriteProperty<Object, @NonNull T> <T extends Object> SavedStateHandleDelegateKt.saved(
    @NonNull SavedStateHandle receiver,
    @NonNull KSerializer<@NonNull T> serializer,
    String key,
    @NonNull SavedStateConfiguration configuration,
    @NonNull Function0<@NonNull T> init
)

Returns a property delegate that uses SavedStateHandle to save and restore a value of type T.

import androidx.lifecycle.serialization.saved

@Serializable data class User(val id: Int, val name: String)
class ProfileViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    val user by
        savedStateHandle.saved(key = "bar", serializer = User::class.serializer()) {
            User(123, "foo")
        }
}
Parameters
@NonNull KSerializer<@NonNull T> serializer

The KSerializer to use for serializing and deserializing the value.

String key

An optional String key to use for storing the value in the SavedStateHandle. A default key will be generated if it's omitted or when 'null' is passed.

@NonNull SavedStateConfiguration configuration

The SavedStateConfiguration to use. Defaults to SavedStateConfiguration.DEFAULT.

@NonNull Function0<@NonNull T> init

The function to provide the initial value of the property.

Returns
@NonNull ReadWriteProperty<Object, @NonNull T>

A property delegate that manages the saving and restoring of the value.

SavedStateHandleKt.toRoute

public final @NonNull T <T extends Object> SavedStateHandleKt.toRoute(
    @NonNull SavedStateHandle receiver,
    @NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap
)

Returns route as an object of type T

Extrapolates arguments from SavedStateHandle and recreates object T

Parameters
<T extends Object>

the entry's NavDestination.route as a KClass

@NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap

A mapping of KType to custom NavType<*> in T. May be empty if T does not use custom NavTypes.

Returns
@NonNull T

A new instance of this entry's NavDestination.route as an object of type T

SavedStateHandleKt.toRoute

public final @NonNull T <T extends Object> SavedStateHandleKt.toRoute(
    @NonNull SavedStateHandle receiver,
    @NonNull KClass<@NonNull T> route,
    @NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap
)

Returns route as an object of type T

Extrapolates arguments from SavedStateHandle and recreates object T

Parameters
@NonNull KClass<@NonNull T> route

the entry's NavDestination.route as a KClass

@NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap

A mapping of KType to custom NavType<*> in T. May be empty if T does not use custom NavTypes.

Returns
@NonNull T

A new instance of this entry's NavDestination.route as an object of type T