When using MVVM on Android, should each Activity have one (and only one) ViewModel?
On MVVM pattern, the ViewModel contains business logic and notifies the View when it needs to be updated. It is also notified by the view about user events.
As I understood it, each Model should have an associated ViewModel. So, if we have the following models:
- User
- Account
We would have the following ViewModels:
- UserViewModel
- AccountViewModel
However, all examples I find about data binding with MVVM, use a single ViewModel for a layout. And recently, Google has introduced the ViewModel class within Architecture Components. This leads me to believe an Activity would have a single ViewModel that would connect to all related Models:
User / Account --> ActivityViewModel
This gets even more complicated if we think of a RecyclerView. Each adapter item could be a ViewModel itself, so an Activity with a RecyclerView would have multiple ViewModels within the list and plus a master one for the remaining view contents (assuming they require information from a ViewModel). For instance:
In this example, we have a list of Account ViewModels and one UserViewModel. How would this be embedded into a single ActivityViewModel?
You should have one ViewModel per View (Activity, Fragment or Custom View), with multiple LiveData, one for each logical unit. In the image one logical unit would be the user data, another logical unit would be the settings data, so you would have two LiveData exposed in the ViewModel.
These concepts can also be visible in the recommended app architecture google presented in the last Google I/O, where an Activity/Fragment has 1 ViewModel with multiple LiveData:
Google suggests that you use 1 ViewModel
per View
(i.e., Activity
or Fragment
) (see https://youtu.be/Ts-uxYiBEQ8?t=8m40s), and then inside each ViewModel
you can have more than 1 type of Model. However, the MVVM principle is to have only 1 Model type per ViewModel
, so Google's presentation contradicts that :/. I guess you'll have to decide what approach works better for your app.
About the list example you mentioned, that is not how you'd do it, for lists you'd use the paging library. You can see details on how to use this at the end of the video I linked above.
One view model is standard. However, even google suggests that you may have more than one view model. That comes quite convenient when you mitgrate a phone app towards a tablet app. When you combind more than one phone views on a single tab view, then it is convenient re-using the models.
If you have the SOLID principles in mind when coding, then the S (single responsibitly of a class) may cause you to use more than one view model.
However, one per view is pretty much standard and you shold have reasons, as metioned above, to use more than one.
What is the relationship between Users and Accounts? If these are two separate, unrelated models, then they should each have their own views and view models. Remember the single responsibility principle: each module should be responsible for only a single part of your logic. That way, any changes to your domain logic or models will only affect that part, and that part only.