Using ViewModel and LiveData in your Android App

A common trap

Since the dawn of Android, application development has been a bit like the wild west. As developers, we want to build fast so sometimes we neglect the architectural design of our applications from the start. A designer hands off the UI and we go over the requirements for our project and start building. The MainActivity starts out lean but we create a bunch of objects for our business logic, hook into framework API’s to start services or leverage hardware from the device resulting in a 2K line file and error-prone code. But we can do much better by taking some extra time to think about separation of concerns within our application. The applications we are building should be modular, extensible and testable. So how do we accomplish this in GUI applications?

Loaded answer: developing an architecture for the application!

Popular GUI architectures:

All these patterns encompass similar concepts. The main idea is we have a Model that contains our business logic, which will be mostly Android agnostic so we can test the code we are writing without the framework dependencies. We have a View that is responsible for displaying information to the user and handling interactions from the user with the on-screen widgets. Finally, we have the ViewModel which is responsible for the display logic for our model (business logic) into the view. But what does that actually mean?

Things may become clearer with the following diagram:

The View is responsible for loading the layout, attaching listeners to UI elements as well as hooking into Android Framework APIs such as system services, custom service implementations, broadcast receivers, etc. Depending on the design choices the view will also be responsible for injecting dependencies or creating the dependencies for the other components in the design.

The ViewModel is responsible for facilitating communication between the view and the data access layer containing application state and business logic.

The Model will handle everything else related to the business decisions of the application including remote connections to REST APIs, data persistence for offline scenarios, and anything else that could be a business rule for the application.

Hopefully, this clears things up for now but if not don’t worry we are going to work through an example.

App Scenario

Let’s think about how we can accomplish the following task: Build an app that lets me search for places using a textual phrase using Google’s Places API. Cool project, I know! But how do we design this in a robust way?

Architecture Components!

In GUI applications there are plenty of design patterns to improve the design of our applications such as MVP, MVC, MVVM, as well as a few others. It has not always been easy to decide which to use when and there is certainly no silver bullet. It has become a common idiom though to use however, we have seen best practices emerge over time in building great apps from developers among the community and open source projects from companies across the world. It was only recently that Google took a stab at actually providing some built-in APIs on Android to help guide the architectural structure of our applications via Architecture Components but wow are they useful.

For our purposes, we are going to look into three components from the new libraries but only one will be the main area of focus.

  1. LifecycleOwner
    • Since the latest release of the support library, we now have activities and fragments implementing the LifecycleOwner interface. So we won’t have to worry about this too much for now but it is important to know it is needed for the ViewModel.
  2. LiveData/MutableLiveData
    • LiveData and MutableLiveData are generic data holder classes that can be observed within a life cycle. Remember LifecycleOwner? These objects allow the data they hold to be observed when changes are made. The distinction between the two, however, is that MutableLiveData exposes the setValue(T) and postValue(T) methods. This means we can change the underlying value and the UI will reflect those changes automatically if we attach an observer in which we update the view. There is also a way to attach an observer without a LifecycleOwner which you can read more about here but we won’t focus on that here.
  3. ViewModel (main area of focus)
    • ViewModel is a class that is responsible for preparing and managing data for an Activity or Fragment. It is where a developer can hook into the business logic and the best part is data outlives the life cycle of the Fragment or Activity it is used within. This means objects are not recreated everytime the screen rotates or your app is backgrounded(unless of course, the system kills your app to free up resources).

Architecture

So we have thought a little bit about the architecture of our app and we will implement the following:

  • Search screen to get user input through a form field
  • Search result screen to display the results
  • Detail screen to display more information about a search result
  • A repository which will make HTTPS request to the Google Places API using Retrofit
  • Business logic class (ViewModel) which will use the repository to get data and manage it

All source code is written in Kotlin and available on Github.

Let’s skip over the easy parts since we already know how to collect input from an EditText and pass it as an extra through a Bundle to a Fragment.

The Search Results Screen layout xml:

The important parts of the layout really are the Toolbar and the RecyclerView everything else is meant to improve the UI/UX.

Place List Fragment:

Note: important information is in the comments above. If you looked through this code you will notice using the MainViewModel we were able to request the places using the query from the extras and search the places API. We also attached a listener which allows us to update the UI when the request finishes.

Place Detail Fragment

If the comments weren’t enough the important thing to note here is since we are attaching the MainViewModel to the hosting activity of these two fragments we viewed the source of above we only need to re-attach to it and our data is still there. This means we can navigate to and from the same place from the list or list of places and the data will persist.

And finally, the MainViewModel

In the MainViewModel we have all our business logic nicely separated from the rest of our application. The MutableLiveData holder class around our PlacesResponse and PlacesDetailsResponse allow us to observe the changes applied to them when the rest call finishes.

Summary

As you can see LiveData and ViewModel are very powerful components that can help build better apps. Hopefully, this shows how powerful the LiveData and ViewModel classes are and convinces you to at least look into using them to help architect your application. In an upcoming tutorial, I will show you how we can test this code easily.

Please leave a comment or share if you enjoyed the tutorial.

Navigation with Architecture Components

Android JetPack

Android Jetpack was announced this week at Google IO 2018 and it is something you should definitely direct your attention towards. In an effort to save developers time, the only resource we have a finite amount of, the Android team has prioritized making it easier to get started building great apps with a collection of libraries that streamline your development flow. The libraries cover four key areas of application development:

  • Foundation – AppCompat, Android KTX, Mutlidex & Testing
  • Architecture – Data Binding, Lifecycles, LiveData, Navigation, Paging, Room, ViewModel & WorkManager
  • Behavior – Download manager, Media & playback, Notifications, Permissions, Sharing & Slices
  • UI – Animations & transitions, Auto, Emoji, Fragment, Layout, Palette, TV & Wear OS by Google

As you can see there are a vast number of important topics bundled into this set of libraries to improve developers lives. Additional information can be found at the developer site.

Fragments Again?

This year at IO the android team presented a lot of talks about all the new features that have been developed under the Jetpack umbrella and even more specifically architecture components. With the release of Navigation in architecture components, Google is once again advocating for the use of Fragments within your apps. And, get this they are pushing for single Activity apps if possible having Fragments do the bulk of heavy lifting leaving only things such as top-level navigation and app chrome for the Activity to handle.

Google spent a lot of time digging into Fragments and listened to developers feedback to solve their biggest pain points through these new architecture components. Today we are going to look at one of the new offerings in architecture components, Navigation.

Getting started

Prerequisite – understanding of Android application development and the Kotlin programming language.

All the source code is available on GitHub.

Head over to the Android Studio download site to get the Android Studio 3.2 Preview to get started using Jetpack. Once installed, create a project that includes Kotlin support and adds an Activity via the new Activity & Fragment + ViewModel option.

Okay, that should have created 3 things:

  • MainActivity
  • MainFragment
  • MainViewModel

Next, open up the app/build.gradle file and add the additional dependencies:

Now we should be all set up. If there is an issue with the Kotlin standard library change:

to

MainViewModel

Let’s start with the source of our data for the list of produce products we will display in our sample app. Remove any code from the generated sample class and replace with the following:

As you can see, we are using the new ViewModel architecture component in our MainViewModel but since we are looking into Navigation, I will cover ViewModel in more detail in another post. Next, let us take a look at the MainFragment.

MainFragment

The MainFragment is the home screen of our app hosted within a single Activity.  It will show a list of produce products to the user and listen for items being tapped from the DataAdapter class. When onClick(item: String) gets called we will use the new Navigation architecture component to show the DetailFragment.

In MainFragment we want to do 4 things:

  1. Initialize our MainViewModel
  2. Setup our RecyclerView
  3. Initialize our Adapter
  4. Implement DataAdapter.Listener

The following code shows just this:

As you can see, in the onClick(item: String) method something interesting is happening. We see no FragmentTransaction but when we run the app tap on an item in the RecyclerView we see our DetailFragment loads with no issue. So what exactly is happening here?

Google added a new way to navigate using fragments without the developer ever needing to deal with FragmentTransactions again. Through the static NavHostFragment.findNavControllerMethod(this) call we obtain a NavController from the new NavHostFragment class, more on this shortly. Once we have our NavController we can call navigate() with either and id from our actions, again more on this in a minute, or passing id with a Bundle. So what is this NavHostFragment?

MainActivity

Before answering this let’s first look at the layout file.

Inside our main_activity.xml, you will notice there is a static fragment placed below the Toolbar within the ConstraintLayout. The fragment has a few things we have not seen before:

NavHostFragment is a new class that helps orchestrate the navigation among fragments, but let us look closer at the other 2 new methods.

  1. app:navGraph is a new attribute that points a file in a res/navigation folder, which contains some XML to describe what the NavHostFragment should do when certain NavActions are performed.
  2. app:defaultNavHost allows us to specify this fragment as the default navigation host allowing it to stick on the top of the stack for this NavController.

So what exactly is this nav_graph.xml file?

The navigation graph is a new XML configuration file for setting up a navigation host and it’s NavController using the new navigation editor in Android Studio 3.2. The following XML sets the MainFragment as the starting point and attaches an action with an animation to the destination of the action, the DetailFragment.

Let’s now look back at the MainActivity code and finish up by explaining the power of the Navigation library.

MainActivity

Inside the MainActivity we want to do 2 things:

  1. Set the toolbar as the supportActionBar and add support for back navigation via the NavHostFragment’s NavController
  2. Override onSupportNavigateUp()

In the example, the ActionBar gets linked to the NavHostFragment’s NavController and then the Activity overrides onSupportNavigateUp() to handle back navigation through the same controller. Wow! That was so easy now we have a single Activity app with a list and a DetailFragment. The NavHostFragment manages the loading of the MainFragment and DetailFragment when the respective NavActions are taken via the view elements of our app and the MainActivity is merely a shell for the up navigation and common chrome.

If you found this post helpful please like or share on social networks. Please leave a comment if you find any mistakes in the snippets or consult the github code for a full implementation.