Most of the time the State Holder I pass to a comp...
# compose
d
Most of the time the State Holder I pass to a composable is an
@Immutable
data class
. But sometimes the State Holder classes have mutable properties backed by
mutableStateOf(…)
. For example the
DrawerState
class. This raises two questions for me. 1. My intuition is not to put classes like
DrawerState
into a
ViewModel
, is that intuition correct? a. Why or why not? 2. What are the heuristics that go into determining when to put a
mutableStateOf(…)
into a State Holder class?
s
TextFieldState also is such a state holder with internal mutable state backed by compose State objects. Would you also be reluctant to put it in the VM?
2. Is a good question I also don't feel like there's a clear cut answer, but... "When the state it handles becomes complicated enough" maybe cuts it? Think of the existing state objects, often they're like that and they expose convenient to use suspend functions (like
hide()
for bottom sheet state for example) and/or convenient to use public state while internally they hide away some complexities regarding how the state changes (think material3 DatePickerState) and so on.
f
I consider a "state holder" a class that holds both state, and some business logic to change said state. It could be considered a "viewmodel lite", and is defined as
@Stable
and not
@Immutable
. The properties from this class are backed by
mutableStateOf
(though I usually have an interface and an implementation, with the interface exposing plain types). If there is only state, a data class, then I don't consider it a "state holder", just a "state data class" and can be marked as
@Immutable
if necessary.
f
0. The immutable data class that you pass is not a "state holder", but it's the UI state. The stateholder is the mutable object holding the state (e.g. mutableStateOf { uiState }) 1. The viewModel should contain business logic. Rarely the state of a drawer is "business logic", but rather an implementation detail of the UI. I'd leave it on the UI side. 2. The principle is usually: is it business logic? Then it goes in the VM. Is it not business logic (hence UI logic)? Then it goes in the *lowest common ancestor* between all the composables that read and write it.
d
@Stylianos Gakis In regards to putting the Compose specific things in the ViewModel, I was thinking that If I want to share my ViewModel in a MultiPlatform project I would want to it to be pure Kotlin. But considering the advent of Compose Multiplatform this seems to be even less of a concern now.
👍 1
Ok, so help out here. Let’s say I have a class like this:
Copy code
class MyListItemState(
  isVisible: Boolean = false,
  ...
) {
  ...
  var isVisible: Boolean by mutableStateOf(isVisible)
}
Would it be fine to put this in the
ViewModel
? And share that ViewModel with Compose Multiplatform?
s
If isVisible is part of the business logic sure. You can use multiplatform compose + molecule for the compose parts. Just make sure to keep that private and instead expose this state as a StateFlow instead, so that all clients can consume it much easier. In fact, we're doing something like that with some presenters that use molecule to handle state. The public API just exposes a StateFlow anyway.