https://kotlinlang.org logo
Title
s

Shakil Karim

12/27/2021, 10:47 AM
What is the correct way to handle Events which are coming from ViewModel, i was trying to follow Official guideline. Launch Effect (ViewState) { If ((ViewState.someBoolean) { Somefunc() } } If ((ViewState.someBoolean) { Launch Effect (true) { Somefunc() } }
c

Chrimaeon

12/27/2021, 12:23 PM
Have a look here https://developer.android.com/jetpack/compose/state#viewmodels-source-of-truth You are not following the guidelines 🙂
a

Albert Chang

12/27/2021, 2:06 PM
State and event are different things. Using a state to represent events is wrong at the first place. You should expose events as a
Flow
and collect the flow in a
LaunchedEffect
.
c

Chrimaeon

12/27/2021, 2:09 PM
But the ViewModel should consume the evens and expose the state otherwise it's not a "view model".
a

Albert Chang

12/27/2021, 2:12 PM
No. There are cases where exposing an event flow to UI layer is reasonable. For example error messages for which you show snackbars.
c

Chrimaeon

12/27/2021, 2:14 PM
why? the error is a "state" triggered from an "event" that should be handled by the view model.
If you always follow this pattern, maintaining your app and testing it is much easier 😉
a

Albert Chang

12/27/2021, 2:18 PM
Does your app always show the error state or it just show a one-time exclamation on error? In the latter case, errors are events instead of a state.
Anyway what the op is doing is basically triggering a one-shot action when a "state" becomes true, which is obviously not what a state is intended to be used.
👍 1
c

Colton Idle

12/27/2021, 3:05 PM
For the one shot action @Albert Chang https://developer.android.com/jetpack/guide/ui-layer/events#handle-viewmodel-events doesn't this contradict your statement? "This UI reacts to changes to the 
isUserLoggedIn
 state and navigates to the correct destination as needed:" I'm still learning, so I'm probably wrong. @Chrimaeon if you want, the docs were recently updated to have a case on snackbars. https://developer.android.com/jetpack/guide/ui-layer/events#consuming-trigger-updates
c

Chrimaeon

12/27/2021, 3:20 PM
As seen in the example the trigger is outside the composable scope, so can haben everywhere. Then in the viewmodel the state is updated and the state is then consumed by the Composable.
a

Albert Chang

12/27/2021, 3:26 PM
The view model notifys the UI with a state, the UI shows a snackbar and when the snackbar disappears (without user interaction) the UI notifys the view model, the view model generate a new state. This flow seems somewhat strange and overly complicated to me. At least IMO using an event flow is much clearer with less code.
👍 2
c

Colton Idle

12/27/2021, 3:52 PM
yeah. its similar to this thread here from a while back involving events: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1640618092111200?thread_ts=1627406028.253800&cid=CJLTWPH7S
😂 1
seems like people are torn on it. im just gonig to follow the recs about it, because i dont want to think about these sorts of things. i rather just accept it and focus on building my business
👍 2
a

Adam Powell

12/27/2021, 4:25 PM
there's no reason why a ViewModel can't be a holder of other objects that implement this kind of state reducing. SnackbarHostState is a good example of this (for exactly this example too!) https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]compose/material/SnackbarHost.kt;l=60
This class's whole job is to take events (callers of the
showSnackbar
method) and reduce those events to state (
currentSnackbarData
). The methods on the
SnackbarData
interface are also events: events published by the UI itself both when the user interacts with the snackbar and when the UI determines that it has shown a particular message for a timeout period
The
SnackbarHostData
has no UI dependencies, so it's safe to keep one in a
ViewModel
or even a global singleton if you feel like it. Composables on any screen in your app can present this using a
SnackbarHost
or your own implementation, since
SnackbarHost
only uses the public API of
SnackbarHostState
. You can test anything that your code does to a
SnackbarHostState
without involving composition or UI at all.
Specifically, many screens in your app can present the same snackbar data from the same
SnackbarHostState
instance without worrying about losing events or which UI consumed the event that a particular snackbar notification is talking about
a

Arjun Achatz

12/27/2021, 5:03 PM
I think the biggest consideration is process death. If you have events that need to live on, go for the UiState approach and save state library. If you don't, a one shot single consumption event stream is good enough. Personally I've never really had to deal with process death, so for me I do the event stream