'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:

enter image description here

In this example, we have a list of Account ViewModels and one UserViewModel. How would this be embedded into a single ActivityViewModel?



Solution 1:[1]

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.

Solution 2:[2]

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.

Solution 3:[3]

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.

Solution 4:[4]

In general it is okay to have 1 View with multiple ViewModels.

View - answers the "how", how should a UI rendered. But it should never answers the "when".

ViewModel - answers the "when", it's the presentation logic and tells when should the view be rendered. ViewModel should never have reference to any View. Instead View observes and listen on ViewModels.

Model - answers the "where", it's the business logic which handles data (local/remote) request. Where to read data and where to write.

As long as ViewModel do not have any reference of View, it should be okay since we can have a situation with Fragment that has its own ViewModel and another ViewModel which comes from its host Activity. We also have a so called shared ViewModel which uses by activityViewModels() that can be use by the Fragments inside the Activity.

You will have a Fragment that has 1 ViewModel own by the fragment itself and 1 ViewModel own by the host Activity.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Franco
Solution 2 Hermann Klecker
Solution 3 Omar Silva
Solution 4