Architecture of Android Apps

Overview

When first building Android apps, many developers might start by relying on Model View Controller (MVC) patterns and usually end up writing most of the core business logic in activities or fragments. The challenge is that writing tests that can validate the app's behavior is difficult to do because the code is often so closely tied to the Android framework and the various lifecycle events. While automated UI testing could be written to validate individual activities or fragments, maintaining and running them over the long-term is often difficult to sustain.

Clean architecture principles, as espoused by Robert Martin (also known as "Uncle Bob"), attempt to focus the developer on thinking through the app's core functionality. It does so by separating the architecture of app into three major layers: how the app shows the data to the user (presentation layer), what are the core functions of the app (domain or use case layer), and how the data can be accessed (data layer). The presentation layer sits as the outermost layer, the domain layer sits in the middle layer, and the data layer resides in the inner layer.

It's important to note that each layer has its own data model, and data can only be exchanged between layers and usually flows only in one direction (i.e. outer to inner, or inner to outer) Anytime data needs to be exchanged, usually a converter is used to map one layer's model to another. In this way, a boundary of separation is created that helps limit changes in one layer to cause unintended side effects in other layers.

At the data layer, every source (i.e. file, network, memory) of data should be represented using the repository data pattern. There are many different ways of implementing this repository pattern, but the ultimate goal is to expose an interface that defines the different queries that need to be performed in order to abstract away the type of data source used. The underlying implementations can therefore be swapped regardless of the type of data source used.

Clean architecture introduces more abstractions and attempts to apply single responsibility principles in Android development. While there may be concerns about this approach adding more complexity, slow performance, and poor testability, it has been shown to work successfully in production apps (see this Droidcon talk or this Droidcon 2016 talk).

Templates

The following template projects are built to act as a starting point for a preferred architecture:

Model View Presenter

In Android app development, the traditional "Model / View / Controller pattern" is often being dropped in preference for the "Model / View / Presenter" pattern. The Model-View-Presenter (MVP) architecture comprises:

  • Model: the data layer
  • View: the UI layer, displays data received from Presenter, reacts to user input. On Android, we treat Activities, Fragments, and android.view.View as View from MVP.
  • Presenter: responds to actions performed on the UI layer, performs tasks on Model objects (using Use Cases), passes results of those tasks to Views.

What we want to achieve by using MVP are simpler tasks, smaller objects, and fewer dependencies between Model and Views layers. This, in turns makes our code easier to manage and test. Major differences from MVC include:

  • View is more separated from Model. The Presenter is the mediator between Model and View.
  • Easier to create unit tests
  • Generally there is a one to one mapping between View and Presenter, with the possibility to use multiple Presenters for complex Views

The easiest method for understanding this is multiple specific examples with sample code. Check out these useful resources for an in-depth look:

Migrating to Clean Architecture

If you're attempting to migrate towards clean architecture without necessarily rewriting your entire code base, your best approach is to first try to isolate and encapsulate your logic by moving it outside of your Activities or Fragments. Moving towards the Model-View-Presenter (MVP), which is a popular way of structuring your presentation layer, should probably be your first step. There is no exact way of implementing this approach, so here are a few recommended links:

References

Clean architecture:

MVVM Pattern:

Fork me on GitHub