AndreiBogdan
02/01/2024, 9:31 AMVita Sokolova
02/01/2024, 9:39 AMprivate val _showError = MutableStateFlow<String?>(null)
val showError: StateFlow<String?> = _showError
fun onErrorShown() {
// we reset flow states to avoid showing errors after subscribing again
_showError.tryEmit(null)
}
For navigation we still use conflated channels in the native app, so I'm also curious to know the best practises for KMP ViewModels:
private val _navigateTo = Channel<NavigationDirection>(Channel.CONFLATED)
val navigateTo = _navigateTo.receiveAsFlow()
AndreiBogdan
02/01/2024, 9:53 AMAndreiBogdan
02/01/2024, 9:54 AMmohamed rejeb
02/01/2024, 10:27 AMLaunchedEffect(state.isSuccess) {
if (state.isSuccess() {
onNavigate()
onClearSuccessState()
}
}
AndreiBogdan
02/01/2024, 10:31 AMmohamed rejeb
02/01/2024, 10:36 AMSharedFlow
for your navigation and to have a ScreenNavigationEvent
sealed interface for each screen and you can emit events from your view model and collect them in your screen and navigate to the destination depending on the event.
But I always get lazy to do that because it requires some more additional work and the other approach is working fine 😄
With this approach you don't need the erase hack because SharedFlow
is going to ensure that the event is going to be collected only once.AndreiBogdan
02/01/2024, 10:37 AMJeff Lockhart
02/01/2024, 4:15 PMMutableSharedFlow
or Channel
with receiveAsFlow
works without the need to reset the state.AndreiBogdan
02/01/2024, 5:01 PMJeff Lockhart
02/01/2024, 5:18 PMStateFlow
, but once a value is collected, resets itself.AndreiBogdan
02/01/2024, 5:45 PMJeff Lockhart
02/01/2024, 6:51 PMChannel
with receiveAsFlow
described in the issue description does work for this, as long as you only intend for and need one collector to receive the events.Pablichjenkov
02/01/2024, 7:01 PMJeff Lockhart
02/01/2024, 7:19 PMjob1
misses SharedFlow
values from when it wasn't yet collecting.
job2
collects all the Channel
values, even the one sent before it was collecting.
job3
doesn't collect any Channel
values because job2
receives them instead.Pablichjenkov
02/01/2024, 7:53 PMJeff Lockhart
02/01/2024, 8:27 PMchannel.isEmpty
if it wants to know if the events haven't been consumed.
The channel can also control its buffer size and overflow behavior. Depending on the type of event, it might make sense for the channel to be conflated like a StateFlow
, like for navigation events. Or it might make sense to buffer multiple events, like for snackbar notifications.Pablichjenkov
02/01/2024, 9:17 PMJeff Lockhart
02/01/2024, 9:24 PMPablichjenkov
02/01/2024, 9:40 PMnon-cancelable
. And that is basically the concern these articles talk about.
1- Start consumption, then
2- Cancelation request comes before the consumption codes executes.
What happens here? - when the consumption starts, if a cancellation comes before the code finishes, is it guaranteed to complete and then cancel? Or it can cancel before finishes.
I recall that was Manuel Vivo's concern.Jeff Lockhart
02/01/2024, 10:12 PMPablichjenkov
02/01/2024, 10:25 PMJeff Lockhart
02/02/2024, 5:07 AMSharedFlow
still receives the event when canceled in the same way.
It's a shame this issue hasn't received any further attention or a proper solution after so many years. The workaround to both send and collect on Dispatchers.Main.immediate
is valid for Android, but unfortunately isn't multiplatform-supported, since immediate
only supports the Main
dispatcher, which isn't available on all platforms.Pablichjenkov
02/02/2024, 5:17 AM