what are you using for state? sealed class or data class? which one is better?
h
what are you using for state? sealed class or data class? which one is better?
m
I often have sealed classes with data class implementations. But I almost always have concrete classes for my states be immutable data classes.
k
☝️ Sealed class or interface to define your state, data class to implement it
z
This is what I do for state
Copy code
sealed interface State {
  object Loading : State
  object Loaded : State
  class Error(val exception: Exception) : State
}
f
I find that sealed classes don't work well when you want to mutate the state, it added complexity
if you have a data class you can do
state = state.copy(foo = bar)
but with sealed classes you first have to find out which state you are in
h
exactly. how one can use sealed classes and change the state like you do in data classes?
z
I use
var state by mutableStateOf<State>(State.Loading)
in my viewmodels and haven't had trouble
h
@zt what if one of the parameters in your state is data class and you want to change one value of that data class but keep all other values same?
z
Use
copy()
f
you first need to d a
when
on all the types and do a copy only if it's the right type, otherwise you need to make a new instance from scratch
h
if you are using sealed class using copy is not possible in an easy way
z
I haven't had to do something like that in my app so far, so I'm not sure
h
@Francesc my point exactly
f
right, that's why I mentioned it adds complexity and I avoided this approach
z
Are you using Flow?
h
I am using MutableStateFlow
f
it doesn't matter if it's
flow
or
mutableState
h
there has to be a better approach
f
the bottom line is that you can only do a
copy
on the right type so you need to have `when`s for each action that mutates the state to find out which state you are in
z
Sure, but there are different approaches to just directly modifying your state. For instance, you could using
combine
to build a stateflow that emits your state. This would work if you had separate flows for each of your mutableStates that make up components of your total state. Take a look at Google’s Now in android app, in their viewmodels, and you will see what I mean
f
this does not really answer the question of how to make a copy because this is always making a new instance of the specific sealed class. If that's how you want to go about it, then that's another approach, but if you want to use the existing state as a stating point for the next state, then this doesn't answer it
h
on the other hand using data class as state makes it really easy to update anything you like and keep existing state as it is but it’s not looking as clean as it looks in sealed approach.
f
you could break your state into sections if that makes sense for your screen,
Copy code
data class MyState(
    val topSection: TopSectionState
    val middleSection: MiddleSectionState
    ...
}
and then you can do
Copy code
state = state.copy(
    topSection = topSection.copy(...)
)
if you have an MVI arthictecture, you could further break the logic in the viewmodel into Middleware classes each responsible for updating one section of the screen
h
I will take a look into that thank you very much
c
I’ve found that it’s best to manage the state of a screen with a single
data class
, rather than with
sealed classes
. The main reason being that in a real application with non-trivial data, it’s not easy to break the state into discrete units like
Initial
Loading
,
Value
and
Failure
and still give a good user experience. Instead, those sealed classes work much better as properties of the data class, and give you more flexibility to create more complex UI states without exponentially increasing the number of sealed subclasses. I’ve got a more thorough explanation in this portion of the documentation for the Ballast MVI library
f
thanks for sharing, that mirrors my experience as well
h
I found this maybe this could be helpful https://stackoverflow.com/a/47624138
f
that seems more like a workaround, and doesn't address any of the complexity concerns that Casey highlights in the linked doc
839 Views