Android Architecture Components

Steven Pungdumri
Published in
4 min readMay 22, 2017

--

For years now, many in the Android developer community have voiced frustration that Google hasn’t adequately offered guidelines on how to build robust, testable apps. Novice developers often find themselves with god activities and fragments that do much more than maintain the UI such as mucking around with business logic, making network calls, accessing the database, and much more. Over the years, developers have proposed design patterns that historically worked well for other frameworks. Today, some of the more popular approaches are MVC, MVP, and MVVM. Developers often research, choose one, then stick with the guidelines of the architecture they picked or use a library with helper components to get started.

Google has now released a set of documentation with accompanying components to offer an opinion on how Android apps should be architected. Let’s take a brief dive into the library in its current state (1.0.0-alpha1 at the time of writing).

Library Overview

  • LiveData — lifecycle aware, observable sources of data. When paired with a LifecycleOwner, LiveData can respond to lifecycle events like pausing updates during a stopped lifecycle.
  • LifecycleOwner — interface implemented by activities and fragments to publish lifecycle events to any observers.
  • LifecycleObserver— observe LifecycleOwners to respond to lifecycle events (implemented by LiveData).
  • ViewModel — a layer to manage and provide data to a specific UI component.

ViewModel

The ViewModel doesn’t modify views directly (in fact it shouldn’t know about the UI components at all), instead it offers up observables for changes, typically using instances of LiveData. It handles the logic needed to initialize, store, and retrieve data used in the UI. This can be shared across activities and fragments, and is safe from lifecycle events such as activity recreation on a screen rotation.

They can destroy our Activities, but they can never destroy our data

Illustrates how the ViewModel scope persists across activities and fragments being destroyed and recreated. Note: destroyed != finished. Image source

LiveData

LiveData provides data using the observer pattern, similar to other reactive libraries. In addition to this, they are lifecycle-aware and respond accordingly to the state of their active observers. For example, LiveData objects will send updates only when their corresponding LifecycleOwners are active (visible to the user), and stop when LifecycleOwners are inactive, since there’s no point updating the UI if it’s not visible to the user. They will also handle cleanup of references and observers automatically when the observed lifecycles are destroyed.

LifecycleObserver

Any object can now listen for lifecycle events by subscribing to them. Simply pass through the LifecycleOwner object to a component that implements LifecycleObserver and call:

lifecycleOwner.getLifecycle().addObserver(this);

From here, the LifecycleObserver can annotate methods to be called on lifecycle events:

@OnLifecycleEvent(Lifecycle.EVENT.ON_START)
void startListening() { … }
@OnLifecycleEvent(Lifecycle.EVENT.ON_STOP)
void stopListening() { … }

The following states are available to listen for: CREATED, DESTROYED, INITIALIZED, RESUMED, STARTED

At any point, the LifecycleObserver can also call

lifecycleOwner.getLifecycle().getCurrentState()

or

lifecycleOwner.getLifecycle().getCurrentState().isAtLeast() 

and switch logic accordingly.

Putting it Together

Image source

The resulting app architecture should resemble this diagram. The Activity/Fragment layer only contains UI logic. The ViewModel(s) encapsulate model data surfaced by instances of observable LiveData. The ViewModel handles the actual source of that data with a reference to components in the Repository layer, which may be pulling from network, cache, database, or a combination of three. This post doesn’t dive into the Repository layer, but if you’re using SQLite in your app it’d be worth checking out Room, Google’s ORM library that provides an abstraction layer over SQLite, which was also recently released.

Recap

Google has responded to the the Android developer community’s ask for an opinion and direction on a clean way to architect Android apps. It comes with no surprise that it pulls ideas from existing libraries that have emerged and become popular (for good reason) over the years, since these ideas have been implemented, tested, and iterated on by the community.

It’s important to know that these architecture components and guidelines are not required by any means. They can be used altogether, in pieces alongside other existing libraries, or not at all. What’s great is we have another resource for building stable, testable apps.

References:

--

--