Introduction to Android App Development With Kotlin: LiveData (Part 10)
Meet LiveData, the observable data holder class that is ''lifecycle aware.''
Join the DZone community and get the full member experience.
Join For FreeWith the ability to retrieve data from your database, it seems appropriate that we display those records for the user to see in a fragment. At this stage, you may be wondering: how do we effectively return this list of movies from the view model to the fragment? Or maybe you are thinking: what should happen if I make a call to the database and, at the same time, the user decides to leave my app to do something else? Should we return the data nonetheless and waste resources or should we not. Luckily, there’s a Google’s Android library we can use that will handle all those awkward edge cases for us. Hello, LiveData.
In this tutorial, we will look into LiveData
, what exactly it is, and how it fits into our application.
LiveData
LiveData
is an observable data holder class that is lifecycle aware. “This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.”
Main advantages of using LiveData
:
- Ensures your UI matches your data state
- No memory leaks
- No crashes due to stopped activities
- No more manual lifecycle handling
At this stage, it’s clear that this library will make our life easier so how do we go about using it? Luckily, we don’t have to import it because it comes included as part of lifecycle-extensions, which we imported when we first started working with the view model.
Here’s the method I use for using LiveData
, which makes the most sense to me.
First, in the view model, let’s add a private instance variable of type MutableLiveData
:
val allMovies = MutableLiveData<List<Movie>>()
MutableLiveData
object type is almost the same as LiveData
object except it exposes two important methods, namely setValue(T)
and postValue(T)
, which we will use.
Next, we will slightly upgrade the retrieveMovies()
method to return a LiveData
object. We will return the allMovies
instance variable we created above but downcasted to LiveData
since a fragment has no business updating it.
fun retrieveMovies(): LiveData<List<Movie>> {
GlobalScope.launch {
val list = mDb?.movieDao()?.getAll()
Timber.i("retrieveMovies list count ${list?.size}")
allMovies.postValue(list)
}
return allMovies
}
Notice how we are also using the postValue
method to notify the observers (i.e. our fragment) of the fetched data.
Finally, it’s time to subscribe to this LiveData
object in the MovieListFragment. In the line where we called the retrieveMovies()
method, all we have to add is add an observer to it
mViewModel.retrieveMovies().observe(this, Observer {
Timber.i("received the movies ${it.size}")
})
Run the app and watch the results
We are now observing the data using LiveData
! You must admit, it was quite simple yet very powerful. The fact that we don’t have to worry about activities or fragments lifecycle is a huge relief. You can now apply this pattern to all of the data calls you will ever need to make.
Conclusion
Today, we were introduced to an awesome library called LiveData
and we put it to use. With a concrete implementation, you can now easily replicate it to add any calls to the database you may need.
With the movies list available to us within the fragment, we should now display it. The way to do it is by using a recyclerview
. More about that in the next tutorial.
The complete working code can be found in this GitHub repo where each lesson is tagged appropriately.
Opinions expressed by DZone contributors are their own.
Comments