Hey Vasiliy,
Great points about the speed of SQL queries. I totally agree about the importance of making sure you have consistent app state after a process restart.
The main purpose of a ViewModel is less about removing the need for loading data from a local database (which there’s no complete escape from anyway) and more about one suggested option for architecting data loading and restoration in an app.
If you don’t use a ViewModel, where are you determining whether your UI data is fully loaded and where are you returning loaded data to? If the answer to both of those questions is “the activity” or “the fragment”, then the benefit of using a ViewModel is that it detangles UI data from UI Controllers (Activity/Fragment). A few reasons why this might be helpful:
- Returning loaded data to a UI controller can be complicated. This is because while you’re figuring out where (network/database/some combination) and how to get your data, your activity instance could be destroyed. In the past, you’d write a Loader to make sure you weren’t returning loaded data to a destroyed activity instance. But writing a loader is non-trivial, loaders are a bit hard to wrap your head around and having all of the LoaderManager callbacks within the activity means the activity is responsible for determining when data should be reloaded. Instead of writing Loader code, why not write ViewModel? The ViewModel class then owns determining when to load data and is a stable place, separate from the UI controller lifecycle, for loaded data to return to. It separates concerns far more cleanly and I’d argue it’s about the same amount of code as writing a Loader.
- Separating concerns makes testing easier.
- Moving UI data to a separate class makes it easier to share UI data between different UI controllers without worrying about how their lifecycles might or might not align. You can have multiple fragments that share state indirectly through a ViewModel. A simple example is shown here.
- If you use ViewModels, you have added bonus of not needing to reload data on config changes.
So “not reloading data” is a bonus but not the main reason you’d use ViewModels (unless your app is one where re-loading is a huge timesaver); the main reason is architectural.
If you’re loading and managing data some other way that resolves these issues, that’s perfectly valid (and do share! Part of the feedback we want is seeing how developers handle these situations in the wild). ViewModels represent one android framework team maintained option for solving this problem that also works with the other components and the guide.
As a side note, I chose a search for a few reasons:
- It’s a common use-case that’s easy to immediately understand
- You have a single activity which changes a lot with user interaction that affects loading data
- The search query is a good example of a unique id that will both not automatically be saved in
onSaveInstanceState()and which can be used to re-load the UI data if the ViewModel is lost
I had a bit of trouble coming up with an example, not because incorporating ViewModels was difficult, but a simple example that required the use of onSaveInstanceState() can be a little tricky. onSaveInstanceState() saves a lot automatically for you, you could choose to persist the “unique id” in local storage instead and if your app has multiple screens the unique id might come from a bundle of extras instead of onSaveInstanceState(). So in those cases, you might end up using other methods than onSaveInstanceState(). It should be noted that none of the advice about when and how to use onSaveInstanceState() has changed with the introduction of ViewModels.
Thanks for reading and your thoughts!