In this article we will dive deep into LiveData component. In case you missed the previous article or don’t know about architecture components then head on to my previous article Introduction to Android Architecture Components.
The code in this article is written in Kotlin. In case you don’t know Kotlin. Read this series of article to get started.
LiveData is a component which holds the value (data holder) and allows to observe for changes in the value. It is designed to hold the data in ViewModel but it can also be used at other places in your application.
It uses Observable pattern to detect changes in the data. It’s pretty similar to RxJava observable with the main difference been, LiveData is lifecycle aware. We will at what lifecycle aware means later.
The main benefit is the fact that our UI components like RecycleView, observe LiveData for changes in the data and LiveData being lifecycle aware it knows about lifecycle of an Activity or Fragment.
In very simple terms, LiveData is just plain data type which has capability to notify it’s observers when data is changed.
Adding it to your project
Add the following dependencies in your app or module
// For Lifecycle, ViewModel and LiveData
compile "android.arch.lifecycle:extensions:1.0.0-alpha9"// Java
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha9"// Kotlin
ViewModel class with the data being
We have just wrapped our data i.e
List to list of live data i.e
LiveData<List> That’s it! Now we just need to use it to observe for changes on our UI.
In our UI
Fragment we will get the
LiveData instance and observe for changes the data and update state of the UI.
For example, we can update the
RecyclerView when data changes maybe due to adding new item or removing an item.
This is all simple usage of LiveData which you’ll mostly deal with.
UI — LiveData — LifecycleOwners
The UI components like
RecyclerView observe changes on the LiveData and update themselves when the live data is changed.
Now you might be worried what happens when the UI is gone, for example if the users pressed home button and maybe after that the data is changed maybe by some other thread and you receive the observe call back. It’s definitely going to crash cause the UI is already gone.
Don’t worry the app is not going to crash. Fortunately the Android Team were aware of this hence they made LiveData lifecycle aware which means LiveData is aware of the state of it’s owners which in this case is
That’s great! But how does LiveData do this?
It gives the provides the following benefits:
Transformations of LiveData
For example, fetching data based upon the
id in the details page
For these tasks the library provides different transformations. There is also provision to write custom transformations using
MediatorLiveData , we will look at them later.
Let’s take an interesting scenario to understand use of
switchMap() transformation. Let’s say you have list of users and when you click on a particular user, a new activity is shown with details of the selected user.
Each time the
userId is changed the
switchMap() transformation is called and
user instance is updated with new value based upon the
When the detail activity is open, the user id of the selected user is notified to
UserViewModel which automatically calls our transformation and the observe is called which updates the UI with the user details.
Technically speaking, the switchMap transformation takes a LiveData, makes the changes, unwraps the value and notifies the observer.
It is similar to switchMap transformation except in this, it takes the LiveData, makes the changes and notifies the observer.
In a nutshell,
— use map() when you may want to make changes to the
LiveDatavalue before dispatching it to the observers and use
— switchMap() when you may need to return a different
LiveDatainstance based on the value of another one.
There might be cases when the default transformations won’t be applicable or sufficient to your needs, you’ll need a custom transformation. To implement your own transformation you can use the
Interesting fact: The default transformations internally use
MediatorLiveDatato make the transformation possible
Writing your own LiveData class
Let’s say you wanted to read a file from storage and want to observe changes on the file then simply using
LiveData won’t help, you’ll need to write your own by extending the
LiveData is a lifecycle aware component hence for custom LiveData class, we need to handle the behavior when the
LifecycleOwner (Activity and Fragment) are present or not, it is done using the
There are 3 important functions while extending
onActive()— It is called when the
LiveDatahas an active observer that means the observer’s lifecycle is in
RESUMEDstate. This means we need to start observing the location updates from the device.
onInactive()— This method is called when the
LiveDatadoes not have any active observers. Since no observers are listening, there is no reason to observe for changes on the data.
setValue()— Calling this method updates the value of the
LiveDatainstance and notifies active observers about the change.
Following is a custom
LiveData class which observes for changes in the file and notifies on any change in the file content. We use
FileObserver API to observe for file changes.
We can use the
onInactive() functions to only listen when there’s an active observer on our data — as long as someone is observing, they can be guaranteed to get the latest data.
onEvent() callback is triggered when the file content changes and we read the complete file and set the new data using
setValue() function which notifies of data change to the active observer.
LiveData is a lifecycle aware component useful to keep our data up-to date which in turn keeps our UI up-to date, even if the UI is re-created due to configuration change. It prevents crashes caused due to destroyed
LiveData with ViewModel, double the advantages of LiveData and make it easier to separate data from UI while keeping the UI up-to date.
Overall, I really like how LiveData component is designed to help us build apps with the reactive nature of Android.