LiveData is data holder which observes changes of a particular view inside an activity/fragment and update it with the latest data.
Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services.
This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.
Imagine you have an app which contains an activity with couple of TextViews with some values, then on orientation change, you need to set values to the TextView again because the activity will be destroyed on orientation change.
By using LiveData you don’t have to worry about the orientation change because the observables do everything for you.
Here are some advantages of using LiveData in your project:
I’ve been using ViewModel with interfaces as a listener and for passing data from my ViewModel to the corresponding activity. I was defining the interface in ViewModel and implementing it in activity/fragment. So whenever some event happens we simply call the method on the interface. This is simple and straightforward approach but this is an anti-pattern because in MVVM we should not have any reference to the view.
This interface we have declared has 3 methods, they are very much self explanatory.
In UsersViewModel we are:
getUsers(message: String)
which take one string parameter and on execution we first call the onLoading(message)
method. Then make an async network call using the repository method getUsers()
, if everything goes well then we will call the onSuccess(response)
method. But if there is some error, we’ll call the onError(error)
.
In UsersActivity class we are implementing the interface, and setting the progress bar in onLoading()
,
and onSuccess()
is used to set data to recyclerview adapter.
The onError()
will show a toast with a particular error.
This violates the MVVM pattern and leads to the problem because the UsersViewModel has the reference to the UsersActivity.
Here, we’ll remove all the interface related stuff and add MutableLiveData which is a type of List<Users>
and is immutable. Also, we will expose one LiveData with the same type which contains the all the data form MutableLiveData which is used to observe in our activity. Then we use the setValue(T)
to set the value to our MutableLiveData.
Here, we’ll remove the interface implementaion and create a function getUsers()
which contains:
users
LiveData, this observer takes one argument (owner) which is basically to identify current lifecycle state. It’ll give us the users list which we sent from our viewModel by using setValue(T)
method of the MutableLiveData.users
which is a public LiveData instance in our ViewModel, we are using it because while using LiveData we ensure that anything outside the UsersViewModel should not be able to manipulate anything in our LiveData. Hence, all the editing and processing should be done by the UsersViewModel class by MutableLiveData. And same would apply to the error observer.getUsers()
method from viewModel which makes a network call to make everything work.Conclusion - LiveData is lifecycle-aware, which handles all the config changes automatically and prevents memory leak. While using MVVM pattern make sure that your activity/fragment is just used for setting the data which is recieved from the ViewModel. Also, your viewModel is dumb and don’t know anything about your views. So, ViewModel should not have any reference to the views.
tags: Android - LiveData - ViewModel - MVVM