Android : Deep dive into SavedStateHandle
SavedStateHandle: APIs, how it works with ViewModel and survive the Configuration changes.

Senior Android Engineer from Bangladesh. Love to contribute in Open-Source. Indie Music Producer.
Search for a command to run...
SavedStateHandle: APIs, how it works with ViewModel and survive the Configuration changes.

Senior Android Engineer from Bangladesh. Love to contribute in Open-Source. Indie Music Producer.
No comments yet. Be the first to comment.
In this series, I will write about Android App Development.
Exploring Caching in Android: Strategies, Implementation, and Considerations for Optimal Performance and Limitations.
A practical guide to choosing the right coroutine primitive for your Android/Kotlin projects

This guide explains what Channels are, when to use them, how to use them correctly, and when NOT to use them β in simple, professional language. 1. What problem do Channels solve? In Kotlin coroutines, you often have multiple coroutines running at t...

Learn how to build preview-safe ViewModels in Jetpack Compose using Hilt.

HandlerInterceptor vs Filter in Spring Boot: A Practical Guide with JNDI Injection Prevention

Simple In-Memory Caching: A Tiny Trick with Massive Impact

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 LinkedHashMapaccordingly. Similarly, when retrieving a value, SavedStateHandle looks up the corresponding key in the LinkedHashMap and returns the value if present.
// 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>
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:
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
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.
*_* 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...