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.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

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:

  1. Creates a flag to track if data has been observed or not.
  2. 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 sets hasBeenHandled to true 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!