Maybe this belongs in <#C5GB1NDGE|android-architec...
# compose
f
Maybe this belongs in #android-architecture but… I’m always conflicted between these two architectural approaches. Should I be striving to have relatively dumb Composables, where the state is passed down from its parent and events are propagated up using callbacks, Or should I instead try to make composables as reusable and independant as possible. Which means giving them a VM, and having communication happen through layers above the VM (repositories, services, etc) Both work (I’ve tried them) I can’t find any pro/cons to justify my decision Maybe mix and matching is the right approach (depending the Composable complexity), what’s your take on this
In the scenario on the left the repository would be reactive, VMs don’t talk to each-other directly
I’m thinking of having dumb Composables (right), until one becomes complex enough that it deserves its own VM (but it’s not always easy to know where to draw the line between simple/complex)
i
The latest video has specific guidance around this:

https://www.youtube.com/watch?v=0z_dwBGQQWQ

- use ViewModels at the screen level, pass state down and events up for subcomponents of a screen
👍🏽 1
👍 3
f
Thank you Ian! Im giving this a watch now
Very clear, looks like this is the way to go 👌 thanks again @Ian Lake!
i
Of course, that doesn't mean that your state can't be split up into smaller pieces; it doesn't need to be monolithic, nor are you constrained to only using one ViewModel even at that higher level
f
Let me see if I got that… you can have multiple VMs… as long as you don’t nest them. This wouldn’t be ok.
Copy code
@Composable
fun MainScreen() {
     val vm = viewModel()
     ....
     Foo()
     ...
}

@Composable
fun Foo() {
    val anotherVm = viewModel()
    ....
}
Also, wont this restriction make it hard for really deep views hierarchies 🤔they would need to bubble up the events though multiple layers of composables
t
I've found that it's not really a big deal, and it means you can be really flexible when moving components around
f
Right, I haven’t actually tried it, maybe it;’s not an issue
it doesn’t need to be monolithic
Would love to learn more about this though, how can I avoid a god VM in very complex screens 🤔 … should I just use 2 or more VMs at the top level
c
This is a very good topic I’ve been struggling to find a good compromise. I recently wrote a todo app to test out how would a data driven UI would work because I was getting stuck having an internal state (for like a checkbox being checked or not) and storing in Realm that this object was checked. In the end instead of having a the state being passed down I’m passing down data. Of course this does work well because checkbox has already a state built in. Bottom line, I’m using state inside of the composable when it’s directly connected to the UI behavior and changing it using data from a repository to avoid inconsistencies. I was thinking about the need of a view model maybe, for the composable. But it worked in a very interesting way when I only had a VM for the view, composables that had a state for their UI presentation and that the changes came from local data. https://github.com/cicerohellmann/to-beetle-do
And about the amount of VMs, best way to be sure about the bulkiness and understanding, invite a fellow dev that it’s a stranger to the project and you may get your answer. I’m in a privileged situation where very few people at my company know compose so I can try and show them my implementations and get a very honest answer about how understandable it is. Also a very good architectural view of it because as they don’t understand it they rely more in architectural knowledge to criticize the code.
f
Thanks Cicerohellmann! I also went with only one ViewModel at the top and passing state down - events up
It seems to work, but I’d like to explore using completely independent Composables with their own VMs in the future and see how it goes. (left approach in the picture above)
d
I'm creating Forms in Compose including specialised
TextField
and Drop-Down List components constructed from
TextField
and
DropDownMenu
. Each component has its own sub-VM to manage loading of data/valid states; validation of input both in real-time and at final submission etc. These are clearly reusable units of business logic that mirror the View layer in structure. Hard to imagine having it any other way... copying and pasting this functionality in a single VM would be 🤢. Structuring presentation logic alongside the View feels natural to me and also encourages keeping the View layer (Compose declarations) as thin as possible, meaning easier portability to other systems/flavours of View layer (e.g. Compose for Web). At the end of the day it's whatever works for you - here's a counter-point 🙂