# Android : Deep dive into SavedStateHandle

## Basic

`SavedStateHandle`, introduced in the **AndroidX** library, provides a convenient way to persist and restore data during configuration changes in Android applications. Under the hood, `SavedStateHandle` leverages several key components and mechanisms to achieve this functionality. We will explore the internal implementation of the Android `SavedStateHandle` and understand how it works.

* `SavedStateHandle` is part of the Android Architecture Components and is tightly integrated with the `ViewModel` class.
    
* It stores `key-value` pairs of data that need to be preserved across configuration changes.
    
* These `key-value` pairs are saved and retrieved by `SavedStateHandle` during the lifecycle of a `ViewModel`.
    

When a `key-value` pair is added or modified in the `SavedStateHandle` internally updates the `LinkedHashMap`accordingly. Similarly, when retrieving a `value`, `SavedStateHandle` looks up the corresponding key in the `LinkedHashMap` and returns the `value` if present.

---

## Public APIs

```kotlin
// To set a value
fun <T> set(key: String, value: T?)

// To get a value
fun <T> get(key: String): T? 

// To remove a value
fun <T> remove(key: String): T? 

// To find a key present or not
fun contains(key: String): Boolean 

// To get a value as LiveData
fun <T> getLiveData(key: String): MutableLiveData<T>

// To get a value as LiveData with a initial value if has null value
fun <T> getLiveData(key: String, initialValue: T): MutableLiveData<T>

// To get a value as StateFlow with a initial value
fun <T> getStateFlow(key: String, initialValue: T): StateFlow<T>
```

---

## Notes

* All public `APIs` must be called from `MainThread`.
    
* `<T>` means any of kind object that is supported.
    
* Before saving a `value`, `set()` method calls `validateValue(value)` to make sure the `value` is listed in the **Supported Objects List** else `throw IllegalArgumentException`
    
* Supported `objects` are:
    
    ```kotlin
    Boolean::class.javaPrimitiveType, BooleanArray::class.java,
    Double::class.javaPrimitiveType, DoubleArray::class.java,
    Int::class.javaPrimitiveType, IntArray::class.java,
    Long::class.javaPrimitiveType, LongArray::class.java,
    String::class.java, Array<String>::class.java,
    Binder::class.java, Bundle::class.java,
    Byte::class.javaPrimitiveType, ByteArray::class.java,
    Char::class.javaPrimitiveType, CharArray::class.java,
    CharSequence::class.java, Array<CharSequence>::class.java,
    ArrayList::class.java, Float::class.javaPrimitiveType,
    FloatArray::class.java, Parcelable::class.java,
    Array<Parcelable>::class.java, Serializable::class.java,
    Short::class.javaPrimitiveType, ShortArray::class.java,
    SparseArray::class.java, Size::class.java
    Int::class.javaPrimitiveType, SizeF::class.java
    ```
    

---

## How does it survive the Configuration changes?

* `SavedStateHandle` is associated with a `ViewModel`. `SavedStateHandle` is primarily designed as an internal mechanism for managing `state` within `ViewModel` instances. It serves as a `container` for persisting and restoring data across configuration changes.
    

`SavedStateHandle` survives configuration changes in Android by leveraging the `ViewModel`'s `lifecycle` and the underlying architecture of the Android framework. When a configuration change occurs, such as a screen rotation, the system destroys and recreates the associated `Activity` or `Fragment`. However, the `ViewModel`, including its `SavedStateHandle` remains **unaffected** by this process.

* **ViewModel Initialization**: When an `Activity` or `Fragment` is created, a new instance of the associated `ViewModel` is created or retrieved. This initialization typically occurs in the `onCreate()` method of the `Activity` or `Fragment`.
    
* **SavedStateHandle Association**: During `ViewModel` initialization, the `SavedStateHandle` is associated with the `ViewModel`. This association is usually established through a dependency injection framework or via the `ViewModelProvider`.
    
* **SavedStateHandle Creation**: The `SavedStateHandle` is initialized with a `Bundle`, which represents the saved state of the `ViewModel`. This `Bundle` is automatically provided by the framework and represents the data that needs to be persisted across configuration changes.
    
* **Bundle Preservation**: When a configuration change occurs, the system destroys the `Activity` or `Fragment` but retains the `ViewModel` instance, including the `SavedStateHandle`. The `Bundle` associated with the `SavedStateHandle` is preserved by the system.
    
* **ViewModel Recreation**: After the configuration change, a new instance of the `Activity` or `Fragment` is created, and the `ViewModel` is recreated. The `SavedStateHandle` is recreated as well, using the preserved `Bundle` from the previous instance.
    
* **State Restoration**: Once the `ViewModel` and `SavedStateHandle` is recreated, the values stored in the `SavedStateHandle` is automatically restored from the preserved `Bundle`. This ensures that the state is maintained across the configuration change.
    

---

## In a nutshell

\*\_\* `SavedStateHandle` is a container that holds supported `objects` according to unique `keys` by leveraging `LinkedHashMap`. Simple `key-value` concept but very **powerful**.

\*\_\* `ViewModel` instance provided by `ViewModelProvider` which is associated with an `Activity`.

\*\_\* Every instance of a `ViewModel` contains an instance of `SavedStateHandle`.

\*\_\* As `ViewModel` is not tied to `Activity` lifecycle, when there are configuration changes, `ViewModelProvider` restores the instance with the associated `Activity` including `SavedStateHandle` state.

---

That's it for today. Happy coding...
