what would be the best way to communicate between two viewmodels scoped to same composables?
with huge codebase, the viewmodels get bloated with chunk of code which i want to separate out into feature specific viewmodels but be able to talk to one another in best way possible
01/20/2023, 2:29 AM
01/20/2023, 7:44 AM
I've had several failed attempts at splitting up my ViewModels such that they can be composed together.
Part of it has to do with me using a single method to forward user actions to the ViewModel instead of using one method per user action. The latter allows use of Kotlin interface delegation, while the former doesn't. The single method uses a sealed class for defining the actions. It might be possible to use sealed interfaces and then define actions that can be used from multiple ViewModels but I haven't tried.
However the bigger problem I have is with aligning the scopes and lifetimes of the split up ViewModels with the over-arching composite ViewModel. I typically have one ViewModel per "screen" which happens to be a destination in a nav host, so I don't know how to create a ViewModel that lives shorter than the one that contains it.
I have a feeling that Square's Molecule library might help in this - to compose Presenters together; but I'm not entirely sure how that would look in code.
In your case since you want them both scoped to the same Composable, it should be possible, but you really should ask the question: Do you want those to ViewModels know about each other? If not, it might be an idea to do the communication through the View. Or another option is for ViewModels to communicate through some other source of truth like your data layer.
01/20/2023, 1:16 PM
Yes I agree with Kiran, you probably should use data layers to hold the truth.
You could also send actions (sealed class) into a flow from an injected class, and listen that flow in the viewmodels who need to. It's mostly the same idea as the one using data layers. May be the solution could be a combination of both
01/20/2023, 3:18 PM
I’ve also tried (and failed) multiple ways to get VMs to communicate with each other in a clean way. It ultimately ends up in a mess, where you have to remember to sync one value with both VMs, and then hope it doesn’t kick of a chain of cyclic updates, or similar such synchronization problems as that. What this strategy lacks is a “source of truth” for that data
The best solution I’ve found is, as Ilan and Kiran mentioned, to lift that shared data out of the ViewModels and into a shared Repository that’s a dependency of both VMs. The Repository holds onto its shared data as a StateFlow, which both VMs can observe.