Issue
Let's say that we have a simple fragment with a view based on the UI state held in StateFlow
in the view model.
On onCreate()
we collect state as usually:
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launchWhenStarted {
viewModel.uiState.collect {
// UI update according to state
}
}
}
Now we navigate to the next fragment - the previous is kept by the fragment manager, but the view is destroyed. On the new fragment, we pop back stack and now is surprising: the previous fragment is recreating the view on the initial state and even if we try to update state flow nothing will happen since it doesn't emit equal data twice one by one.
So, how to restore the view state after return to the fragment?
Solution
Maybe a bit later but what you are looking for is repeatOnLifeCycle
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { ... }
}
}
repeatOnLifecycle together with lifecycleScope.launch allows you to collect flows from a Fragment or Activity.
The main difference with your approach is that launchWhenStarted will run you collection function ONCE the UI State is started, but will not repeat the collection when a fragment is restored, while repeatOnLifeCycle will create a new coroutine starting the collection everytime the lifecycle scope reaches the specified state (hence the name) and will cancel it when the lifecycle reaches the opposite state (for example, if you specified STARTED, then the coroutine will be cancelled on onStop).
In addition to that, the launchWhenX documentation nowadays indicates the following
Caution: This API is not recommended to use as it can lead to wasted resources in some cases. Please, use the Lifecycle.repeatOnLifecycle API instead. This API will be removed in a future release.
PD, lifecycleScope.launch { ... } creates a coroutine, and is required as repeatOnLifecycle is a suspend function (suspend functions run on a coroutine or another suspend function)
Answered By - Rodrigo Soria
Answer Checked By - Candace Johnson (JavaFixing Volunteer)