https://kotlinlang.org logo
g

ghedeon

03/19/2019, 10:29 AM
The more I use shared viewmodels like google suggests, the more I think it's a bad practice. (It's when you share activity VM between multiple fragments). You end up having 2 VM's for one fragment view. You pull something from the activity VM, something from the fragment VM, multiple sources of truth, thats already against the idea of 1:1 view-controller relation. So, probably to make it cleaner, you can try to merge 2 VMs via some sort of VMReducer, trying to combine some livedatas, idk.. Eventually, in your fragment VM you'll introduce some init call,
initWithDataFromActivityVM()
that you'd call in onViewCreated, which is again seems stupid, because ideally you'd want a normal constructor injection... Looks like a mess so far. Wouldn't a dagger scope be a perfect fit? Like, define a shared data holder and scope it to the activity and inject it into your fragments?
r

rkeazor

03/19/2019, 11:57 AM
The sharedViewModel is just supposed to be used as a interractor between the fragments and there activities. Prior to that you would have to create a interface/interractor . I am not sure, what a Dagger Scope would do for it ... But I also don't see nothing wrong with it, especially if your using LiveDate observers, its almost the same thing, but simpler .Without having to create your own interfaces all over the place .
g

ghedeon

03/19/2019, 12:17 PM
I'm not talking about the old interface approach, it's even worse. I'm saying create a shared holder object, inject it into acivity and fragment VMs and communicate through it. Also, scope it to activity, so it's cleared when activity is gone.
r

rkeazor

03/19/2019, 9:37 PM
@ghedeon that's more of a anti pattern. Viewmodels should be reusable components. If you start creating objects to communicate between the 3 than the Viewmodels become coupled together
g

ghedeon

03/19/2019, 10:15 PM
No. It's like saying that if you inject a Repository into multiple viewmodels they become coupled.
the SharedDataHolder, or SharedLogic that I mentioned above is like a repository with a smaller scope and lifecycle limited by the activity. I can actually use the regular repository, inject it into both fragments and share data like so. But usually this data is not worth to be persisted to disk and you wouldn't want to keep the singleton beyound the activity existence. That's where the dagger scope comes in play — to limit the lifespan of the shared object.
r

rkeazor

03/19/2019, 11:10 PM
What Kind of logic are you actually trying to contain in this viewHolder object?
g

ghedeon

03/19/2019, 11:23 PM
It's not a view holder, we don't talk views here. A classical example would be some kind of a long onboarding flow, where you keep collecting data in order to create an account at the end. Multiple fragments collect Name, Phone, Address, Selfie, Proof Of Identity, etc... Storing this to a repository doesn't make sense untill it's complete. Storing this into a parent activity VM requires sharing this VM between fragments. And I'm wondering if moving this stuff into a dedicated SharedDataHolder and injecting it into fragment's VM will make it easier.
r

rkeazor

03/20/2019, 2:25 AM
Well you wouldn't have to do that, because remember you can still pass in data to Fragments, through Argument Bundles. However if your doing MVVM, VMs shouldn't have any connection with other viewmodels, and Views are meant to observe changes of the viewmodels. Creating this dataHolder would mean you would have to create callbacks from one viewmodel to another.Than it would be no different than having interactors in the presenter . But now the whole idea of views being the observers is broken, because now other viewmodels are also observing
4 Views