Android Jetpack: ViewModel
Articles Blog

Android Jetpack: ViewModel

August 25, 2019

Google I/O 2017, we announced the
Lifecycle Library. The Lifecycle Library is a
set of libraries and guidance for avoiding memory leaks
and solving common Android lifecycle challenges. Now the Lifecycle
Library has hit 2.0. It’s part of Jetpack. And it includes new
integrations with data binding. This is a tour of the Lifecycle
Library’s ViewModel class. A ViewModel holds
your app’s UI data while surviving
configuration changes. Here’s why that’s
actually useful. Rotating your phone is
considered a configuration change. Configuration changes
cause your whole activity to get torn down
and then recreated. If you don’t properly
save and restore data from the destroyed activity,
you may lose that data and end up with weird
UI bugs or even crashes. So enter the ViewModel,
which, of course, survives configuration changes. Instead of storing all of
your UI data in your activity, put it in the ViewModel instead. Now, this helps with
configuration changes, but it’s also just general
good software design. One common pitfall when
developing for Android is putting a lot of
variables, logic, and data into your activities
and fragments. This creates a large,
unmaintainable mess of a class and violates the single
responsibility principle. You can use ViewModels to easily
divide out that responsibility. The ViewModels will be
responsible for holding all of the data that you’re
going to show in your UI. And then the activity
is only responsible for knowing how to draw
that data to the screen and receiving user interactions,
but not for processing them. If your app loads
and stores data, I suggest making a
repository class, as described in the “Guide
to App Architecture.” Make sure your ViewModel
doesn’t become bloated with too many responsibilities. To avoid this, you can
create a presenter class or implement a more fully
fledged clean architecture. OK, so to make a
ViewModel, you’ll end up extending
the ViewModel class. And then you put your
UI-related instance variables that were previously in your
activity into your ViewModel. Then in your
activity’s onCreate, you get the ViewModel from
a framework utility class called ViewModel Provider. Notice the ViewModel Provider
takes an activity instance. This is the
mechanism that allows you to rotate the device, get
a technically new activity instance, but always ensure that
activity instance is associated with the same ViewModel. With the ViewModel
instance, you can use Getters and
Setters to access UI data from your activity. If you want to modify the
default constructor, which currently takes
no parameters, you can use a ViewModel Factory to
create a custom constructor. Now, this is the simplest
use case of a ViewModel. But the ViewModel class is
also designed to work well with LiveData and data binding. Using all of these together,
you can create a reactive UI, which is just a fancy way of
saying a UI that automatically updates whenever the
underlying data changes. This assumes all of your
data in your ViewModel that you plan to show on
screen is wrapped in LiveData. You then should set up
data binding as normal. Here’s an example
XML with the data binding layout tag
and the variable tag for your ViewModel. Then in your
activity or fragment, you associate the variables used
in the XML with the binding. Here’s an example
with an activity. There’s one new line of
code, setLifecycleOwner. This allows the binding to
observe your LiveData objects in the ViewModel. And it’s essentially
the magic that lets the binding update
whenever the LiveData updates and the ViewModel’s onscreen. You can now directly
reference LiveData fields from your ViewModel in your XML. If you combine this
with binding adapters, you can move much
of the boilerplate logic out of your activity. Note that this became
available at Android Studio 3.1 and higher, so make sure
you’re on the correct version. To learn more, check out
the Introduction to LiveData in the docs. OK, I’m going to finish off
with a few best practices. First tip, you should never
pass contexts into ViewModels. This means no passing in
fragments, activities, or views. As you saw earlier,
ViewModels can outlive your specific activity
and fragment lifecycles. Let’s say that you store an
activity in your ViewModel. When you rotate the screen,
that activity is destroyed. You now have a ViewModel
holding a reference to a destroyed activity. And this is a memory leak. So if you find yourself needing
application contexts, which outlive ViewModel lifecycles,
use the Android ViewModel subclass instead. This includes a reference to
the application for you to use. OK, second tip. ViewModels are meant
to be used in addition to onSaveInstanceState. ViewModels do not
survive process shutdown due to resource restrictions. But onSaveInstance bundles do. ViewModels are great for
storing huge amounts of data. onSaveInstanceState
bundles, not so much. Use ViewModels to store as
much UI data as possible so that that data doesn’t need
to be reloaded or regenerated during a configuration change. onSaveInstanceState,
on the other hand, should store the
smallest amount of data needed to restore the UI state
if the process is shut down by the framework. So for example, you might
store all of the user’s data within the ViewModel but just
store the user’s database ID in onSaveInstanceState. Hopefully this has inspired you
to try out the new ViewModel class in your apps
either by itself or with the other
architecture components. To learn more about
using ViewModels or any of the information
that I just mentioned, check out the
documentation below. [JET BLAST]

Only registered users can comment.

  1. I am new to android, so I have a myriad of doubts hovering my mind. Is view model is similar to MVP or MVVM ?

  2. That t-shirt though!! 👌 Anyways thank for the tips at the end. Wondering how it applies with people already following MVP to build the app so far

  3. I currently use MVP, so can I replace my Presenter to an ViewModel Class? or viewModel is the Data layer?

  4. I love Android but Google always makes the most confusing API's in comparison to Apple. Like why do I have to go through all this just to save the data in a variable when a screen rotates

  5. Does view model contain the data to be posted to API? Eg for login, should we have to use viewModel and UserRepository to post username and password to API.

  6. Screen rotation is a bad example for config-changes as it's trivial to handle it yourself in the Activity.

  7. @AndroidDevelopers at 1:44 you have a diagram with 5 boxes (Activity, ViewModel, Repository*, Presenter*, and more*).

    It would be really nice to see videos of the creations (or snippets) of those concepts (Repository, Presenter, and more) and why it might be good to use them.

    I have seen code in the samples but it is intermingled with everything that I lose sight of why it's important.

  8. Is there a way to check in onCreate or any other method that process was killed and ViewModel lost data? How can we check if we need to load again something from database? Thanks!

  9. Android is such a mess. Who cares about data being gone after rotation if your process can be killed and everything will be gone anyway. Because of that viewmodels are worthless to me. This will only make developers think that the data in viewmodels is always available

  10. It will very easy for me to store my data in static functions. Why don't you guys make a thing in xml which will hold data in it and re use it in simply another xml file

  11. I don't understand how can I know in onCreate() if I should use the viewmodel or the bundle? How do I know if I'm in onCreate only because of a configuration change in which case I can use the viewmodel, or because there was a lack or resources, which means the view model was destroyed and then I should use the bundle?

  12. i want to change in two view of 2 different activity at same time. Those changes should be same in both activity, so can you help me how i can do this? My view should be update

  13. The issue I have with this is it seems y'all are just focusing on Kotlin. Rather than doing two videos of the same content for both Java & Kotlin.

  14. I spent a lot of hours in trying to migrate my APP to use this ViewModel but I came across something that just feels so overkill to me.

    It's still not save from being destroyed when the device is low on RAM. So I still need to rely on the savedInstance bundle to make sure the variables aren't gone when the activities is destroyed by the OS.

    So I found myself keeping an extra copy of the variable in my fragment/activity, just so I could write it back to the viewModel when the instance was restored and had a state.
    This seems like a lot of work for me just to keep it separated.
    My application doesn't even support rotation.

    What are your takes on this? I would really like to delegate the instanceSaving to the viewModel so I don't have to write the same code so many times 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *