Introduction to Android Architecture Components

Put the magic back into Android app development

In Nov 2017 Architecture Components v1 was launched. This is a big deal because for the longest time it was very difficult to deal with certain use cases which would crop up all the time in mobile app development.

Things like dealing with configuration changes when rotating a screen, and sharing app state data between fragments and activities were difficult.

While these difficulties are not insurmountable, the fact that they crop up in so many common scenarios have had a negative impact on the developer experience on Android and didn’t make it feel magical. 😠

Architecture Components puts the magic back into Android development! 🎩

What is it?

There are quite a few patterns out there for app architectures, such as MVP, MVVM, and unidirectional. I’m a huge fan of unidirectional, and I like MVVM too. There are 3 parts of M-V-VM, the Model, View, and ViewModel. Let’s take a look at what each of these are.

View — This is the UI component that is in a layout and rendered on the display.

ViewModel — Views subscribe to the data they are interested in from the ViewModel. So when this data changes it can be broadcast to any interested observers.

  • The ViewModel is responsible for preparing data for consumption by the View.
  • The ViewModel’s state is stable across the lifecycle of Activities and Fragments. So as an Activity is torn down and rebuilt (on an orientation change) it can use the same ViewModel. And you can scope the lifetime of these ViewModels to the Activity lifetime as well, so that when the Activity is finished (not destroyed), then the ViewModel can be cleaned up.
  • LiveData is an interesting piece of a ViewModel that you can wrap any data that changes quite rapidly and these changes have to be reflected in UI components.
  • ViewModels should not hold references to any Views. And if they need an ApplicationContext, then you can use AndroidViewModel which supplies this.
  • You don’t directly create a ViewModel, instead you ask the system to find you one. And the system ends up creating the ViewModel and managing what it’s scope is based on this. Basically you have to use a factory method to get a reference to a ViewModel instead of just creating one yourself using a constructor.

Model — This is where your underlying data is actually stored. The model can be backed by local persistence stores, and synchronized with remote data sources. You can use Room to make it easier to work with SQLLite (on device) and have Room generate the ORM layer for you. Or you can use Firebase for persistence, which automagically syncs its state across multiple platforms. You have a lot of flexibility in what you choose. You can even use something like Redux in addition to Firebase to be your Model.

This article is focused on the ViewModel and LiveData parts of the Architecture Components. I will be covering Lifecycle awareness and Models in other articles.

Example

I’ve created a simple app that showcases how you might use a ViewModel and LiveData in your apps. You can get this sample on GitHub.

The sample just has 1 Java file — MainActivity.java. This Activity loads its state from a StateViewModel, which contains two pieces of data. Here’s the entire Activity.

Data # 1. There’s a UUID String that is generate the first time this StateViewModel is created and this is displayed in the UI. This String does not change for the lifetime of the Activity. It is stable across configuration changes. So as you rotate the screen, and the Activity is destroyed and then recreated (but not finished), the same UUID String will be displayed in the UI. When you finish the Activity by pressing the back button, or by going to the task switcher and swiping the Activity away, then the ViewModel will be destroyed and onCleared() will be called.

Data # 2. The ViewModel also creates a ScheduledExecutor that runs a simple task every second. This task simply updates a counter, and it generates a log message (“tick”, or “tock”). This Executor also sets the value of this counter in a CounterLiveData object. The UI actually subscribes to this LiveData object and when it changes the UI gets updated with the current count. This too is stable across configuration changes. When the Activity is finally finished, the onCleared() method actually shuts the executor down. Also, you have to be mindful of which thread the CounterLiveData’s value is set.

Adding Architecture Components to your project

Read more about how to modify your build.gradle file on developer.android.com. Here’s a simple build.gradle file snippet just for Lifecycles, ViewModel, and LiveData.

Further exploration

  • Codelab to get started with Android lifecycle-aware components
  • “Model View ViewModel on Android” article on medium
  • “Deep dive into Data Loading with Architecture Components” on medium
  • Tutorial on Architecture Components — part 1, part 2