Create an App That Uses LiveData and ViewModel in Java

C
Photo by Anders Jildén on Unsplash.

Among the wide range of tools that were released with Android Jetpack, Android Architecture Components, LiveData, and ViewModel are particularly useful. I’m creating this tutorial in response to Ashton Jones, who expressed that there are very few examples for integrating these Architecture Components with Google Firestore.

In this tutorial, you will learn how all these elements interact, creating a fully functional app with a back end (Firestore) and a front end (Android app) based on Google technologies.

In this first part, we will start by building the Android project. For illustrating the use of LiveData and ViewModel, we will create an app simulating a shopping grocery list.

Download the starter project from my website.

This is a simple Android Java project. It just contains a MainActivity.java file and the corresponding layout. Once the Gradle sync finishes, run the app and you should see a HelloWorld screen like in Image 1 below:

Image 1: The initial view of the app.

Setting Up the Project’s Architecture

Once you get this working, you will create the folder structure of the app. Mobile architectures are widely discussed, but since Android introduced Architecture Components, they gave us a guideline pointing towards MVVM. In this first part of the project, you will focus on the View and ViewModel.

Under the Android project view in the left panel, create two new packages: one called “View” and another called “ViewModel.” Then drag MainActivity.java inside the View package. The resulting project structure should be similar to the one shown below in Image 2:

Image 2: Resulting structure after adding the View and ViewModel packages.

The next step is to create the ViewModel. Right-click on the ViewModel package and select New > Java Class. Give it a name, preferably with the suffix ViewModel — I will name it MainActivityViewModel.java. With these two files, we are able to work with both LiveData and ViewModel.

Photo by Thomas Grillmair on Unsplash.

Creating the ViewModel

Begin by creating your ViewModel. The first thing you need to do is extend the Android Architecture Components ViewModel library. Your class definition should look like this:

public class MainActivityViewModel extends ViewModel {

And if it is not imported automatically, also add the required dependency with the following line of code:

import androidx.lifecycle.ViewModel;

Then you will create an object to hold the shopping list. This object needs to be a MutableLiveData List of type String because your shopping list items are going to just be the names of the items.

In a more realistic scenario, you would probably have a ShoppingItem object under your “model” package (which we didn’t create) and get the properties of this item, but I’m trying to create a minimal example. Create the list with this line of code inside the MainActivityViewModel class:

private MutableLiveData<List<String>> shoppingList;

The purpose of the variable above is to hold all the shopping list items in a LiveData object.

Getting LiveData Asynchronously

In this first part of the project, you will be simulating the asynchronous call of the data with a timer. The first thing you need to do is retrieve the list and then add it to the shoppingList variable created in the previous step. Add this function in the MainActivityViewModel.java class:https://medium.com/media/fcd1c4aae2074039de519de077471add

This code validates whether the shoppingList is empty, and if that’s the case, it creates a new object and loads the shopping list into it.

You will need another function to load the list. Add it below getShoppingList() with the code below:https://medium.com/media/983d1d629b4fd4d6b1007fe99c2c2409

Let’s review the code above separately because it’s a bit long:

  1. You create a handler. The purpose of this handler is to hold the code in the function so that it executes after some time.
  2. You tell the handler to delay the execution by the number of seconds in its second parameter (line 6).
  3. In these lines, you create a sample shopping list that will be populated by a third-party service: Firestore.
  4. The purpose of the shuffle is to see whether the data is refreshed at any point. One important aspect of LiveData is that, unlike other types of data, it is not lost when certain actions take place (e.g. when an orientation change happens).
  5. This line of code assigns the “downloaded” (simulated) data into the local object of MutableLiveData.
  6. As mentioned in point #2, this is setting a delay of 5k milliseconds for the data to “load.”
Photo by Drew Saurus on Unsplash.

Troubleshooting

If you are getting errors in the project after following the steps above, read this part to troubleshoot. Otherwise, you can skip to the next section.

These are the most common problems you may have.

The project should be set to Java 8

In the loadShoppingList() in point #2, you may notice we have an arrow (->). This is called a lambda expression and it is only supported in Java 8. To fix this, go into File > Project Structure and select Java 1.8 in the fields of Source Compatibility and Target Compatibility:

Image 3: Setting the project to Java 1.8.

Importing the incorrect dependencies

It is common in Android and Java to have similar dependencies with different functionalities. When Android Studio imports dependencies automatically, it sometimes gets the wrong one. Make sure your imports are like the ones below:https://medium.com/media/11d2aec1865bdceca6b7fcbf32737c78

If you are still having trouble, take a look at the ViewModel code below:

Image 4: Complete ViewModel class.
Photo by Matt Milton on Unsplash.

Testing the App

After adding the code above, the app should have no changes. It should compile and run successfully, but you will still be seeing the HelloWorld empty screen. This is because we only implemented the ViewModel, which is the communication between the Model and the View, but we still haven’t bound it to the View itself.

Image 5: App after adding the ViewModel.

Connecting the View to the ViewModel

As mentioned above, now you are going to work with the View so that the data loaded from the ViewModel is displayed correctly.

Configuring the XML of the View

Open activity_main.xml, which is located in app > res > layout. Remove the “Hello World” text view and add the code below:https://medium.com/media/164583568b42fbfd30a26b3931c0ed55

This code has two XML items:

  1. The Progress Bar is what is commonly known as a “spinner,” which will be shown on the screen for as long as the info delays to load (5k milliseconds for what we already coded).
  2. The ListView, which will show the shopping list items once loaded.

If you run the app at this point, you will see the Progress Bar (spinner) on the screen, but it will never show the list, as it is still not paired with the view code in MainActivity.java. Run it to see this and verify that your code is working. Your app should look like the screen below:

Image 6: Screen with the progress bar spinning.

Adding Android lifecycle dependencies

For the ViewModel to work, you will need to add the lifecycle extensions dependency to build.gradle(Module: app):

implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'

Android Studio will request Gradle to sync. Do it and it should be successful.

Displaying the data

Now open MainActivity.java, which we moved to your View folder. In the onCreate method below the setContentView() line, add this code:https://medium.com/media/ec714e7120d6b67513b65fe5d0ca4a43

Again, let’s review each line:

  1. You initialize the ListView and get it from the XML.
  2. The same for the progress bar: We initialize it and get the view from the XML. Then you set it to visible — to be shown while the data is loaded.
  3. Next, you initialize your ViewModel, using the ViewModelProvider provided by Android Jetpack. In short, ViewModelProvider is a class that stores the ViewModel and makes it available throughout the app so all the classes that need it can access the information.
  4. Once you have the ViewModel, you call the getShoppingList() method. As you may recall, that method is asynchronous. It will take five seconds and then return the data. That’s why you are observing the response.
  5. Once the shopping list is received, you create an array adapter to create the list view. You will be using layout.simple_list_item_1, which is a pre-provided XML for ListViews that are part of Android OS.
  6. Then you assign the adapter created in the previous step to the ListView.
  7. Finally, you hide the Progress View and show the data.

Required imports

Some imports are needed for this code to work. Some will be done by Android Studio automatically and you will need to add others manually. Here are all the imports that MainActivity.java should have:https://medium.com/media/bccb2efafcde6b06e12f40c34a0c1131

With all this working, you should be able to test the app and see your list appear after five seconds of waiting:

Image 7: Shopping list displayed on the screen.

Conclusion

Great! We now have an app implementing LiveData and ViewModel. In the next part, we will integrate Firestore to this app so the data is loaded from a remote source. If you want to see how the project should work when complete, you can download the finished project from my website.

If you have any doubts, don’t hesitate to leave a comment and I will reply as soon as possible.

Until next time, thanks for reading!

About the author

Evana Puig

Add Comment

By Evana Puig

Evana Puig

Get in touch

Mobile Developer expert in Android and iOS, with 10 years of experience. Visit me at evanapuig.com. Author, and topic master at raywenderlich.com