Referencing nglauber's answer, I found I was getting repeated observations of the same result, until I switched from calling SavedStateHandle.remove()
to setting the value of the LiveData
to null
instead.
@Composable
fun <T> NavBackStackEntry.GetOnceResult(resultKey: String, onResult: (T) -> Unit) {
val resultLiveData = savedStateHandle.getLiveData<T>(resultKey)
resultLiveData.observeAsState().value?.let {
resultLiveData.value = null
onResult(it)
}
}
See, SavedStateHandle.getLiveData()
actually returns a MutableLiveData
, rather than just a generic LiveData
. I was quite surprised as first, until I realized that this must be intentional, to let you modify the saved state via the MutableLiveData
(which it does in fact do, as opposed to simply modifying the LiveData
itself).
I got this idea when I saw the documentation for SavedStateHandle.remove()
:
Removes a value associated with the given key. If there is a LiveData and/or StateFlow associated with the given key, they will be removed as well.
All changes to androidx.lifecycle.LiveDatas or StateFlows previously returned by SavedStateHandle.getLiveData or getStateFlow won't be reflected in the saved state. Also that LiveData or StateFlow won't receive any updates about new values associated by the given key.
I added some logging to confirm that while normally, the call to getLiveData()
on each recomposition returns the same LiveData
instance again, calling SavedStateHandle.remove()
causes it to subsequently return a different LiveData
(which gives you the old value, causing the duplicate observation).