Overview
What is SavedStateFlow?
SavedStateFlow
is a Kotlin StateFlow that can survive the Android process death.
Why SavedStateFlow?
SavedStateHandle
is a great tool to persist state across the Android process death, however this only officially supports reactive updates through LiveData
. There is a nice extension function that exists in the support library that can convert LiveData
to a Flow
, however using this directly in a ViewModel
test requires setting up the test to work with LiveData
and LiveData
can technically have a null value.
This is where SavedStateFlow
comes in being a simple wrapper around SavedStateHandle.getLiveData() while enabling non null initial values exposing the state as a StateFlow
.
Basic Usage
Inject a SavedStateFlowHandle
into a ViewModel
by using the extension function on SavedStateHandle
.
val savedStateHandle: SavedStateHandle = TODO()
val savedStateFlowHandle: SavedStateFlowHandle =
savedStateHandle.toSavedStateFlowHandle()
Info
Please refer to the samples to see how to get a reference to SavedStateHandle
.
- manual injection using the
AbstractSavedStateViewModelFactory
- The
saved-state-flow-hilt
artifact automatically scopesSavedStateFlowHandle
toViewModel
's so there is no need to get a reference to aSavedStateHandle
.
Once a SavedStateFlowHandle
is created, inject it in a ViewModel
and retrieve a SavedStateFlow
.
class MainViewModel(
savedStateFlowHandle: SavedStateFlowHandle,
private val newsDataSource: NewsDataSource
) : ViewModel() {
private val query: SavedStateFlow<String> =
savedStateFlowHandle.getSavedStateFlow(
viewModelScope = viewModelScope, // scope for updates to be collected
key = "main-viewmodel-query-key", // unique key for the property
defaultValue = "" // used when there is no previously saved value upon restoration
)
init {
observeQuery()
}
fun updateQuery(query: String) {
this.query.value = query
}
private fun observeQuery() {
viewModelScope.launch {
query.asStateFlow()
.flatMapLatest { query ->
// fetch the results for the latest query
newsDataSource.fetchQuery(query)
}
.collect { results ->
// Update with the latest results
}
}
}
}
Warning
Since SavedStateFlow
is a wrapper around SavedStateHandle
, the following note from the documentation should be observed.
State must be simple and lightweight. For complex or large data, you should use local persistence.