Wrote a bit about representing view state as a sin...
# feed
z
Wrote a bit about representing view state as a single object. Learn how to design your state classes, and how to actually use them in practice - lots of small tips in this one! Designing and Working with Single View States on Android https://zsmb.co/designing-and-working-with-single-view-states-on-android/
πŸ‘ 4
πŸ‘ 11
a
Based on the techniques used in the post and some of the challenges you cited, you might enjoy #compose πŸ™‚
K 1
z
Oh, can't wait for it to be stable and be combined with all this πŸ˜„
c
We had this debate in our team. I advocated for sealed classes but we ended up using plain data classes for View State, and now I actually prefer it. The complex example in our situation is just
uploadProgressText.isVisible = viewState.shouldShowUploadProgress
The logic is now moved to the ViewModel and the view is as dumb as possible: It just sets some properties on a bunch of views. This way we can write more tests in ViewModels and avoid testing views. Admittedly this is not perfect. There are situations where we cannot keep the ViewState shallow, but in general its works well for us.
πŸ‘ 2
b
You might enjoy mavericks as well: https://github.com/airbnb/mvrx
a
We have also started using sealed classes for rendering states☺️
c
@zsmb nice article! I'm still new to implementing an architecture in an app but this sounds like a really solid way to go. Might be out of scope for your article, but how do you handle "events" such as navigateToScreenX or showToast. Those aren't state right? @Adam Powell I think you mentioned something about the above a while back if i recall correctly. You mentioned something about your UI layer just being able to render state and it should be smart enough to not repeat work if you kept setting the same state over and over. Do you have any thoughts for how a navigation event or showing a toast would be best?
z
That's correct, you'd still need a separate mechanism for dealing with those kinds of events / effects. It was out of scope for this article, but I'll cover it later!
c
Hopefully I will see it on the #feed Thanks again @zsmb Really enjoyed the article.
a
Right now for events we are handling them sealed class ViewState{ object NavigateToSettings: ViewState() }
a
Events and state are distinct from one another, that's right. State is always declarative. You can have an, "I am looking at the settings screen" state, but you cannot have a, "navigate to settings" state. "Navigate to" is an imperative command/request, not a state.
Some other bit of code needs to process events as they arrive and apply any necessary changes to state that might result. "Navigate to settings" may result in changing the state, "I am looking at the login screen" to, "I am looking at settings," but the same event might have no visible effect if you were already looking at settings when it arrived.
a
YesπŸ€”
c
@Adam Powell thanks. I like the way you phrased that. Made it click. Much appreciated
☝️ 1
πŸ‘ 1
a
Just took the time to read this now @zsmb, great article!
πŸ‘ 2
c
@Adam Powell not to bring this up again... state vs events makes sense to me for navigation... as in... navigation commands are DEFINITELY events... but I think showing a snackbar could be declared as state, and the same for showing an alert dialog. Would you agree or disagree there?
a
framed appropriately, yes: "current snackbar state" and, "current dialog state" are fine as state. The current snackbar state might include a queue of messages to display, and manage that queue. You might process event messages like, "show snackbar message X" by adding messages to that queue.
c
Thanks! I think I'm getting it!
a
I used this as a concrete example recently: https://gist.github.com/adamp/47f2762d70bc33a5e2c75a31413ec202
ignore my placeholder snackbar-minus-behavior in that example since there's a real one available in compose too πŸ˜„
πŸ‘ 1