LiveData & ViewModel — Making your own magic
--
User Experience(UX) is probably the most critical part of any product creation. To the final user it doesn’t a matter if you use the best material to build your product or the best algorithms to create your software or if you do it as efficient as possible, if your product doesn’t offer a good experience to the user it won’t use it, that’s simple.
User experience is composed of a lot of elements, for instance: UI composition, navigation pattern, colors, fonts, data accuracy, etc. On this post we will focus on data accuracy and how Google architectural components can help us to create apps that keep automatically synchronized the UI with the data on the model.
LiveData
LiveData is an observable data holder class
As Google defined it, LiveData is a class that has only one property, it allows us to save/hold any object into that property. But LiveData is more than that, it is an observable class, which means it implements the observable design pattern, which allows us to subscribe entities that will be notified when the data contained on the LiveData class change. But there is one more feature that makes LiveData a very good option to include it on our project. LiveData class is lifecycle-aware, which means it respects and it is aware of the lifecycle state of the observer subscribed to it.
If you want to learn more about lifecycle-aware components and how to create your own, I strongly recommend reading my article about it.
The reasons to use LiveData can be summarized in the follows:
- Data/UI synchronization: Because LiveData follows the observable pattern it will notify the UI of any changes, this ensures perfect data synchronization between the two layers without any manual data change verification.
- No more life-cycle related crashes: Since LiveData is a lifecycle aware component it ensures to remove any lifecycleObserver when its status is
destroyed
, avoiding memory leaks due to unused/inexistence references. Also, LiveData will only send notification about data change only to the observers that are on an active state likeonResume.
- No more manual data update: Observable pattern allows to avoid manual work to update and synchronize the UI with our data. When a configuration change happens or when it returns from an inactive state to active state it will receive the latest data right after it came back, this happens on the
OnCreate
when theViewModelProviders
is called, as we will see below
ViewModel
ViewModel is a helper class which is part of the Android Architecture Components
, it helps us to store, manage and prepare UI related data in a lifecycle conscious way. The main benefit of the ViewModel
is that it is created the first time and if the Activity, Fragment or any other LifecycleOwner
is destroyed or recreated by the system, the next time it starts it will receive the same ViewModel
created before. It works like a Loader
(AsyncTaskLoader and CursorLoader)
As we noticed in the image above, the ViewModel is kept alive even when the Activity is destroyed or reconstructed due to a configuration change for example. When the activity is finished
the ViewModel
calls the onCleared()
method to clean up any remaining resource and avoid memory leaks.
We must keep in mind:
- A
ViewModel
class shouldn’t have any reference toLifecycleOwner
, like Activity or fragment, or to thecontext
, this makes the unit testing easier ViewModel
object can containLifecycleObservers
, such asLiveData
objects, but aViewModel
must never observe changes to lifecycle-aware observables, this has to be done on theLifecycleOwner
- If the
ViewModel
needs theApplication
context it should extendAndroidViewModel
and receive theApplication
on the constructor
Ok, let’s check the code
For this article, we will continue using the example created for the article about Room
I posted some months ago, you can visit and read the article on this link to get context about the sample or learn about Room
. Also, all the sample codes are written using Kotlin, if you don’t know Kotlin or you want to learn more, I would invite you to visit this link and read my article about it.
The first thing we need to do is to update our gradle file. It should look like the following
App.gradle
As we mentioned above, ViewModel
object can contain LifecycleObservers
, such as LiveData
object, so that let’s see how do they interact with each other.
MainViewModel.kt
Things to notice here:
- Our custom ViewModel class have to extend from
ViewModel.
- The
ViewModel
class receives only one parameter on the constructor, which is the repository that handles our data. This class is out of the scope of the article but it can be consulted on the repository of this example. - The class has another property, besides the repository, which is a
MutableLiveData
object that contains/holds a list ofGenders
. This means we can subscribe to this property to be aware of its changes and react to them, as we will see below. ALiveData
object can hold any type of object, in this case it is declared as Mutable since we want to be able to modify its content. - Finally, we have a ViewModelFactory which implements
ViewModelProvider.Factory
interface, this is necessary if you need to pass any parameter to your ViewModel, if not you omit that fragment of code
Now let's see how to use our ViewModel
MainActivity.kt
What are we doing?
- We are getting an instance of our database.
- Then, we are getting an instance of our ViewModel using the ViewModelProvider, this provider will check if there is an instance of the same class already created if so it will return it, with all the data up-to-date. If a
ViewModel
has not been created yet, it will be created for us. This ensures each time a configuration change or any similar event happens, we won’t lose the current state of our data nor we will create a new instance of the ViewModel each time. - Finally, we are subscribing to observe and react properly to any change that occurs to the list of gender store on the ViewModel.
If you don’t need to pass any parameter to the ViewModel
class you can omit the implementation of the ViewModelProvider.Factory
interface, as we mentioned before, and the call to get an instance of the ViewModel
can be simplified like the following example
And that’s it :). We have learned how to start building a Reactive MVVM architecture by using Android Architectural components, we will have a more detailed article about reactive apps very soon.
Also! The whole code of the project can be found from here. Thanks for reading!