Skip to content

Instantly share code, notes, and snippets.

@marcellogalhardo
Last active July 23, 2023 23:46
Show Gist options
  • Save marcellogalhardo/2a1ec56b7d00ba9af1ec9fd3583d53dc to your computer and use it in GitHub Desktop.
Save marcellogalhardo/2a1ec56b7d00ba9af1ec9fd3583d53dc to your computer and use it in GitHub Desktop.
A helper function to let you expose a MutableStateFlow from a SavedStateHandle.
/**
* Returns a [StateFlow] that access data associated with the given key.
*
* @param scope The scope used to synchronize the [StateFlow] and [SavedStateHandle]
* @param key The identifier for the value
* @param initialValue If no value exists with the given [key], a new one is created
* with the given [initialValue].
*
* @see SavedStateHandle.getLiveData
*/
fun <T> SavedStateHandle.getStateFlow(
scope: CoroutineScope,
key: String,
initialValue: T
): MutableStateFlow<T> {
val liveData = getLiveData(key, initialValue)
val stateFlow = MutableStateFlow(initialValue)
// Synchronize the LiveData with the StateFlow
val observer = Observer<T> { value ->
if (stateFlow.value != value) {
stateFlow.value = value
}
}
liveData.observeForever(observer)
stateFlow.onCompletion {
// Stop observing the LiveData if the StateFlow completes
withContext(Dispatchers.Main.immediate) {
liveData.removeObserver(observer)
}
}.onEach { value ->
// Synchronize the StateFlow with the LiveData
withContext(Dispatchers.Main.immediate) {
if (liveData.value != value) {
liveData.value = value
}
}
}.launchIn(scope)
return stateFlow
}
@marcellogalhardo
Copy link
Author

marcellogalhardo commented Jul 23, 2023

Hey @PatrickKuijpers, that would work but keep in mind you would block those functions to be used with primitives and other supported types (such as lists), I think. That isn't a problem per see, so go ahead if these are the only types you need in your project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment