Android: How to share data between Fragments using ViewModel and LiveData (Android MVVM)
In this article we will show you how to share data between Fragments using the MVVM Architectural Pattern. To achieve this we will be using LiveData and ViewModel.
If you would just like to see the code, I created a sample app which you can find on GitHub here:
MVVM stands for Model View-ViewModel and is an Architectural Pattern that separates your UI code from your logic code. This allows you to have a cleaner codebase that is more readable and easier to maintain. Using ViewModel with LiveData for sharing data between fragments is just one application of the MVVM pattern that demonstrates its usefulness. Let’s dive a little bit deeper into what exactly ViewModel and LiveData are:
LiveData is an observable data holder class that is also lifecycle-aware. Essentially this means that the LiveData respects the lifecycle of other app components such as fragments or activities and only notifies Observers of changes when they are in an active state (Started or Resumed). If an Observer is inactive then it is not notified of changes to the LiveData object. You might think this is a problem if, for example, you are in Fragment A sending data to Fragment B and B hasn’t started yet. This is not an issue however, as when a Lifecycle becomes active it receives the most up to date data automatically. You can use LiveData with all types of data from simple Strings to HashMaps.
The ViewModel class is a helper class for UI controllers (Such as Activities and Fragments) that is responsible for preparing data for the UI. Like LiveData, the ViewModel class is also Lifecycle-aware. It is designed to prevent assigning excessive responsibility to a UI controller and make code easier to maintain and more efficient. We will use a ViewModel class to house our LiveData objects which will then be used to share data between our Fragments.
If you would like to delve more into all the usages of LiveData and ViewModel I would highly recommend reading the documentation here: https://developer.android.com/topic/libraries/architecture/livedata and https://developer.android.com/topic/libraries/architecture/viewmodel
Now let’s start coding!
First, we need to add this dependency to your app level build.gradle:
For this example we will be sending a simple String between our fragments. Do note however, that you can send most any type of data, such as ArrayLists, as well.
Now we will create the ViewModel class which will essentially be our intermediary between the two fragments we want to connect:
Let’s walk through that code:
You might notice that we create something called a MutableLiveData object whereas earlier we used LiveData. This is because the methods we will eventually use to set the LiveData values, setValue and postValue, have protected access in LiveData. Since LiveData is immutable we need to use MutableLiveData instead to expose those methods.
So, firstly you will need to create the MutableLiveData object of the data you want to be observed. Remember, this can be most any data type but we are using a String variable called name.
Then you will need to create a setter and getter for the MutableLiveData. The setter is what you will call from the 1st fragment to set the value of the LiveData object which will, in turn, notify all observers registered to that LiveData object and call their onChanged methods. In most cases you will use setValue if working from the main thread, but Note: If you are setting the value from a background thread you must use postValue instead. The getter will check if the MutableLiveData object is null and, if it is, create a new object. The getter is what you will observe from the 2nd fragment.
Now that we set up the ViewModel class we have to set up our fragments to send and receive the data. First, you will have to create an object of the SharedViewModel class and, in each Fragments onCreate, initialise it like so to get the ViewModel class:
Next, in the 1st fragment we will need to figure out how we want to set the LiveData object. In the sample app for this tutorial we set an onClickListener on a submit button and call the ViewModels’ .setNameData method inside it:
There are some instances where using the setter, in this case setNameData, may give a NullPointerException. In that case, you can use the getter and call setValue through that instead.
Now in the 2nd Fragment we will have to add the code which will listen to the LiveData and update the String value. We will create an Observer object, initialise it and override its onChanged method. Then we will attach the observer to the LiveData object. All of this will be inside onCreate:
Inside the onChanged method we call setText on a TextView we have set up the receive the String value. Outside the method we call the ViewModels’ getter and attach the observer to it using .observe. We will then pass in a Lifecycle owner and the observer.
That’s all! If done correctly you should be able to send data from one fragment to another. If you have any questions leave a response below and I’ll get back to you!