# SavedStateHandle

Artifact: [androidx.lifecycle:lifecycle-viewmodel-savedstate](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/lifecycle/SavedStateHandle.+class:androidx.lifecycle.SavedStateHandle) Added in [2.3.0](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#2.3.0)

*** ** * ** ***


```
public final class SavedStateHandle
```

<br />

*** ** * ** ***

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 |
|---|
| `@VisibleForTesting SavedStateHandle()` Creates a handle with the empty state. |
| `@VisibleForTesting SavedStateHandle(@NonNull Map<@NonNull String, Object> initialState)` Creates a handle with the given initial arguments. |

| ### Public methods |
|---|---|
| `final @NonNull SavedStateContainer` | `@MainThread asContainer()` Returns the underlying `SavedStateContainer` managing this `SavedStateHandle`. |
| `final void` | `@MainThread clearSavedStateProvider(@NonNull String key)` Clear any `SavedStateProvider` that was previously set via `setSavedStateProvider`. |
| `final boolean` | `@MainThread contains(@NonNull String key)` |
| `final T` | `@MainThread <T extends Object> get(@NonNull String key)` Returns a value associated with the given key. |
| `final @NonNull MutableLiveData<@NonNull T>` | `@MainThread <T extends Object> getLiveData(@NonNull String key)` 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 SavedStateContainer` | `@MainThread getOrCreateContainer(@NonNull String key)` Retrieves an existing nested `SavedStateContainer` associated with `key`, or creates and registers a new child `SavedStateContainer` if none exists. |
| `final @NonNull SavedStateHandle` | `@MainThread getOrCreateSavedStateHandle(@NonNull String key)` Retrieves an existing nested `SavedStateHandle` associated with `key`, or creates and registers a new child `SavedStateHandle` backed by the child container if none exists. |
| `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>` | `@MainThread keys()` 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` | `@MainThread setSavedStateProvider( @NonNull String key, @NonNull SavedStateRegistry.SavedStateProvider provider )` 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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#2.3.0)

```
@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`.

| Parameters |
|---|---|
| `@NonNull Map<@NonNull String, Object> initialState` | initial arguments for the SavedStateHandle |

## Public methods

### asContainer

Added in [2.12.0-alpha05](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#2.12.0-alpha05)

```
@MainThread
public final @NonNull SavedStateContainer asContainer()
```

Returns the underlying `SavedStateContainer` managing this `SavedStateHandle`.

### clearSavedStateProvider

Added in [2.3.0](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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` |

### getOrCreateContainer

Added in [2.12.0-alpha05](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#2.12.0-alpha05)

```
@MainThread
public final @NonNull SavedStateContainer getOrCreateContainer(@NonNull String key)
```

Retrieves an existing nested `SavedStateContainer` associated with `key`, or creates and registers a new child `SavedStateContainer` if none exists.

| Parameters |
|---|---|
| `@NonNull String key` | identifier of the container |

| Returns |
|---|---|
| `@NonNull SavedStateContainer` | existing or newly created child `SavedStateContainer` instance |

### getOrCreateSavedStateHandle

Added in [2.12.0-alpha05](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#2.12.0-alpha05)

```
@MainThread
public final @NonNull SavedStateHandle getOrCreateSavedStateHandle(@NonNull String key)
```

Retrieves an existing nested `SavedStateHandle` associated with `key`, or creates and registers a new child `SavedStateHandle` backed by the child container if none exists.

| Parameters |
|---|---|
| `@NonNull String key` | identifier of the child handle |

| Returns |
|---|---|
| `@NonNull SavedStateHandle` | existing or newly created child `SavedStateHandle` instance |

### getStateFlow

Added in [2.5.0](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#2.3.0)

```
@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

Added in [2.3.0](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt#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

Artifact: [androidx.lifecycle:lifecycle-viewmodel-savedstate](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/lifecycle/serialization/SavedStateHandleDelegate.kt+function: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.

```kotlin
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

Artifact: [androidx.lifecycle:lifecycle-viewmodel-savedstate](https://developer.android.com/jetpack/androidx/releases/lifecycle.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/lifecycle/serialization/SavedStateHandleDelegate.kt+function: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`.

```kotlin
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

Artifact: [androidx.navigation:navigation-common](https://developer.android.com/jetpack/androidx/releases/navigation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/navigation/SavedStateHandle.kt+function: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

Artifact: [androidx.navigation:navigation-common](https://developer.android.com/jetpack/androidx/releases/navigation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/navigation/SavedStateHandle.kt+function: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` |