https://kotlinlang.org logo
Title
a

abbic

08/22/2022, 12:25 PM
hello, i have a screen with events i am refactoring from livedata to compose. previously i would handle events by having them on one livedata and doing
viewmodel.events.observe { when (event) etc etc }
now my instinct is to have the events be a val on the uiState like
UiState(val event)
and then in the composition
SomeScreen(uiState) {
   LaunchedEffect(uiState.event) {
      when (event) etc etc
   }
}
but this causes a problem where in livedata you could post the same event in a row multiple times and the observer would trigger each time. i have to assume that if you copy the uiState and set the same event now the LaunchedEffect wont trigger. I can clear the event manually in the state each time, but the slight overhead makes me wonder if there's a better way to do it?
f

Filip Wiesner

08/22/2022, 12:27 PM
State != Event You should not represent events as a state. Consider using
SharedFlow
for this.
You can collect this flow in your UI
LaunchedEffect(eventFlow) {
    eventFlow.collect { event ->
        when(event) { ... }
    }
}
a

abbic

08/22/2022, 12:32 PM
awesome, thank you for the quick reply
a

Ale Stamato

08/22/2022, 3:28 PM
You might want to take a look at this post alternatively: https://twitter.com/manuelvicnt/status/1532324889255940098?lang=en-GB 🙂
f

Filip Wiesner

08/22/2022, 4:30 PM
Right, I forgot about these new Android patterns. While I don't really agree with it, the article is worth reading at least. My (bad) experience with reducing events to state might be different than yours...
f

Francesc

08/22/2022, 6:21 PM
actually for Compose the recommendation is to treat events as state. Have a list of events, do a
LaunchedEffect
on the list, handle one, tell the viewmodel you handled it, the viewmodel will remove it from the list and your
LaunchedEffect
will trigger again so you can handle the next