SavedStateHandle
public final class SavedStateHandle
A handle to saved state passed down to androidx.lifecycle.ViewModel. You should use SavedStateViewModelFactory if you want to receive this object in ViewModel's constructor.
This is a key-value map that will let you write and retrieve objects to and from the saved state. These values will persist after the process is killed by the system and remain available via the same object.
You can read a value from it via get or observe it via androidx.lifecycle.LiveData returned by getLiveData.
You can write a value to it via set or setting a value to androidx.lifecycle.MutableLiveData returned by getLiveData.
Summary
Nested types |
|---|
public static class SavedStateHandle.Companion |
Public constructors |
|---|
|
Creates a handle with the empty state. |
@VisibleForTestingCreates a handle with the given initial arguments. |
Public methods |
|
|---|---|
final void |
Clear any |
final boolean |
@MainThread |
final T |
@MainThreadReturns a value associated with the given key. |
final @NonNull MutableLiveData<@NonNull T> |
@MainThreadReturns a |
final @NonNull MutableLiveData<@NonNull T> |
@MainThreadReturns a |
final @NonNull MutableStateFlow<@NonNull T> |
@MainThreadReturns a |
final @NonNull StateFlow<@NonNull T> |
@MainThreadReturns a |
final @NonNull Set<@NonNull String> |
Returns all keys contained in this |
final T |
@MainThreadRemoves a value associated with the given key. |
final void |
@MainThreadAssociate the given value with the key. |
final void |
@MainThreadSet a |
Extension functions |
|
|---|---|
final @NonNull ReadWriteProperty<Object, @NonNull T> |
<T extends Object> SavedStateHandleDelegateKt.saved(Returns a property delegate that uses |
final @NonNull ReadWriteProperty<Object, @NonNull T> |
<T extends Object> SavedStateHandleDelegateKt.saved(Returns a property delegate that uses |
final @NonNull T |
<T extends Object> SavedStateHandleKt.toRoute(Returns route as an object of type |
final @NonNull T |
<T extends Object> SavedStateHandleKt.toRoute(Returns route as an object of type |
Public constructors
SavedStateHandle
@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
@VisibleForTesting
public SavedStateHandle(@NonNull Map<@NonNull String, Object> 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.
Public methods
clearSavedStateProvider
@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 |
a key previously used with |
contains
@MainThread
public final boolean contains(@NonNull String key)
| Returns | |
|---|---|
boolean |
true if there is value associated with the given key. |
get
@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 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<Array<Parcelable>>("KEY").map {
it as CustomParcelable
}.toTypedArray()
getLiveData
@MainThread
public final @NonNull MutableLiveData<@NonNull T> <T extends Object> getLiveData(@NonNull String key)
Returns a androidx.lifecycle.LiveData that access data associated with the given key.
| See also | |
|---|---|
getLiveData |
getLiveData
@MainThread
public final @NonNull MutableLiveData<@NonNull T> <T extends Object> getLiveData(@NonNull String key, @NonNull T initialValue)
Returns a androidx.lifecycle.LiveData that access data associated with the given key.
`LiveData<String> liveData = savedStateHandle.get(KEY, "defaultValue");`
Keep in mind 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 if you want to avoid dispatching null to observers.
`String defaultValue = ...; // nullable
LiveData<String> liveData;
if (defaultValue != null) {
liveData = savedStateHandle.getLiveData(KEY, defaultValue);
} else {
liveData = savedStateHandle.getLiveData(KEY);
}`
Note: 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 observe the result as an 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()
}
getMutableStateFlow
@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<Array<Parcelable>>(
"KEY"
).map { array ->
// Convert the Array<Parcelable> to an Array<CustomParcelable>
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.
getStateFlow
@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 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()
}
keys
@MainThread
public final @NonNull Set<@NonNull String> keys()
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
@MainThread
public final T <T extends Object> remove(@NonNull String key)
Removes a value associated with the given key. If there is a LiveData and/or StateFlow associated with the given key, they will be removed as well.
All changes to androidx.lifecycle.LiveDatas or StateFlows 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.
| Returns | |
|---|---|
T |
a value that was previously associated with the given key. |
set
@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 LiveDatas or StateFlows.
| Parameters | |
|---|---|
@NonNull String key |
a key used to associate with the given value. |
T value |
object of any type that can be accepted by Bundle. |
| Throws | |
|---|---|
kotlin.IllegalArgumentException |
value cannot be saved in saved state |
setSavedStateProvider
@MainThread
public final void setSavedStateProvider(
@NonNull String key,
@NonNull SavedStateRegistry.SavedStateProvider provider
)
Set a SavedStateProvider that will have its state saved into this SavedStateHandle. This provides a mechanism to lazily provide the SavedState of saved state for the given key.
Calls to get with this same key will return the previously saved state as a SavedState if it exists.
Bundle previousState = savedStateHandle.get("custom_object");
if (previousState != null) {
// Convert the previousState into your custom object
}
savedStateHandle.setSavedStateProvider("custom_object", () -> {
Bundle savedState = new Bundle();
// Put your custom object into the Bundle, doing any conversion required
return savedState;
});Note: calling this method within SavedStateProvider.saveState is supported, but will only affect future state saving operations.
| Parameters | |
|---|---|
@NonNull String key |
a key which will populated with a |
@NonNull SavedStateRegistry.SavedStateProvider provider |
a SavedStateProvider which will receive a callback to |
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 |
@NonNull SavedStateConfiguration configuration |
The |
@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 <Error class: unknown class><@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 <Error class: unknown class><@NonNull T> serializer |
The KSerializer to use for serializing and deserializing the value. |
String key |
An optional |
@NonNull SavedStateConfiguration configuration |
The |
@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 |
@NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap |
A mapping of KType to custom NavType<*> in |
| Returns | |
|---|---|
@NonNull T |
A new instance of this entry's |
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 |
@NonNull Map<@NonNull KType, @NonNull NavType<@NonNull ?>> typeMap |
A mapping of KType to custom NavType<*> in |
| Returns | |
|---|---|
@NonNull T |
A new instance of this entry's |