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.
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.
SavedStateHandleis part of the Android Architecture Components and is tightly integrated with theViewModelclass.It stores
key-valuepairs of data that need to be preserved across configuration changes.These
key-valuepairs are saved and retrieved bySavedStateHandleduring the lifecycle of aViewModel.
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.
Public APIs
// 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
APIsmust be called fromMainThread.<T>means any of kind object that is supported.Before saving a
value,set()method callsvalidateValue(value)to make sure thevalueis listed in the Supported Objects List elsethrow IllegalArgumentExceptionSupported
objectsare: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?
SavedStateHandleis associated with aViewModel.SavedStateHandleis primarily designed as an internal mechanism for managingstatewithinViewModelinstances. It serves as acontainerfor 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
ActivityorFragmentis created, a new instance of the associatedViewModelis created or retrieved. This initialization typically occurs in theonCreate()method of theActivityorFragment.SavedStateHandle Association: During
ViewModelinitialization, theSavedStateHandleis associated with theViewModel. This association is usually established through a dependency injection framework or via theViewModelProvider.SavedStateHandle Creation: The
SavedStateHandleis initialized with aBundle, which represents the saved state of theViewModel. ThisBundleis 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
ActivityorFragmentbut retains theViewModelinstance, including theSavedStateHandle. TheBundleassociated with theSavedStateHandleis preserved by the system.ViewModel Recreation: After the configuration change, a new instance of the
ActivityorFragmentis created, and theViewModelis recreated. TheSavedStateHandleis recreated as well, using the preservedBundlefrom the previous instance.State Restoration: Once the
ViewModelandSavedStateHandleis recreated, the values stored in theSavedStateHandleis automatically restored from the preservedBundle. 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...




