LiveData Tutorial for Android: Deep Dive
In this Android tutorial, you’ll learn about LiveData which is a core architecture component, and how to use it to its full potential in your app. By Prateek Sharma.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
LiveData Tutorial for Android: Deep Dive
30 mins
- Getting Started
- Lifecycle Aware Components
- LiveData and MutableLiveData
- Initialize, Update, Observe LiveData
- Synchronous vs Asynchronous Update
- LiveData in Action: Example One – Implement Search
- LiveData in Action: Example Two – Update Progress
- Transformations
- Transformations.map v/s Transformations.switchMap
- Transformations.switchMap – Example
- MediatorLiveData
- Example
- Custom LiveData
- Create Custom LiveData
- Consume Custom LiveData
- Optimize API Calls
- Handle Phone Rotation
- Event State Handling
- Multiple Event Emit Problem
- Solution
- RxJava vs LiveData
- Where to Go From Here?
Multiple Event Emit Problem
You will notice that even when you press back now, you can’t navigate back to the movie list screen. This is because, when you press the back button, observers in MovieListFragment.kt attach to LiveData once again and they dispatch the latest value. Since navigateToDetails
already has the tapped movie’s title, it again navigates to the MovieDetailFragment.kt with the same movie title repeatedly.
Navigating to the detail screen is an event and occurs many times. But do you need to react every time the event occurs? No, you can react to an event only once and reject reacting to further events.
Solution
First, in the root directory, create a class Event
in Event.kt:
class Event<out T>(private val content: T) {
}
This declares a class which can contain any type of data.
Next, add following code to return the data only once:
//1
private var hasBeenHandled = false
//2
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled)
null
else {
hasBeenHandled = true
content
}
}
Here’s what this code does:
- Creates a flag to track if data has been observed or not.
- Creates a function that you’ll invoke from outside world to get the data. This returns
null
if data has already been observed else returns the data. Also, it setshasBeenHandled
totrue
to block further reacting on data.
Next, open MainViewModel.kt and update _navigateToDetails
declaration with the below code:
private val _navigateToDetails = MutableLiveData<Event<String>>()
val navigateToDetails: LiveData<Event<String>>
get() = _navigateToDetails
_navigateToDetails
now holds Event
of String
.
Next, replace onMovieClicked()
function with the following code:
movie.title?.let {
_navigateToDetails.value = Event(it)
}
Similarly, _navigateToDetails
now holds event of movie title.
Lastly, open MovieListFragment.kt and update navigateToDetails
observer with below code. Take note of the import statement.
import androidx.navigation.fragment.findNavController
...
mainViewModel.navigateToDetails.observe(viewLifecycleOwner, Observer {
it?.getContentIfNotHandled()?.let { movieTitle ->
findNavController().navigate(
MovieListFragmentDirections.actionMovieClicked(movieTitle)
)
}
})
This uses getContentIfNotHandled()
to get data only when it is not handled before, hence avoiding multiple firing of events.
When you select a different movie other than before selected, it will still work because, in onMovieClicked()
function you create a new Event each time, that resets the hasBeenHandled
flag to false
.
Build and run the app for the last time:
RxJava vs LiveData
You’ll often fall into a situation where you’ve to choose between RxJava and LiveData. Both of them have their limitations. It is good practice to not consider LiveData beyond the Presentation Layer as it has a smaller toolkit compared to RxJava. RxJava being a robust toolset has many operations to manipulate data in streams, which can help in dealing with data or backend layers. As RxJava comes with the bigger toolset, it requires a longer time to get comfortable with as compared to LiveData.
You can use Both RxJava and LiveData with Room Persistence Library. LiveData is compatible with Data binding whereas RxJava is not. This suggests that for business logic use RxJava and for UI state management use LiveData. Yes, you can use both of them in the same codebase. LiveDataReactiveStreams
offer a simple interface that allows you to convert RxJava streams to LiveData in a direct way.
Congratulations!!
In this tutorial, you’ve successfully learned:
- How to Transform LiveData
- How to use Mediator LiveData
- Create a custom LiveData
- The recommended way of handling states
Where to Go From Here?
Download the final project using the Download Materials button at the top or bottom of this tutorial.
You’ve covered most of the LiveData in this tutorial, but there’s plenty of places where you can use LiveData. As in the MoviesApp example, you can integrate Room to store favorite marked movies and show them in case there is no internet. For further reading, have a look at LiveData Overview official document.
Hope you enjoyed the tutorial. If you have any questions or comments, please join the forum discussion and comment below!