Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Discover the Benefits of Android Clean Architecture

Eshvar Mali

Mobile App Development

All architectures have one common goal: to manage the complexity of our application. We may not need to worry about it on a smaller project, but it becomes a lifesaver on larger ones. The purpose of Clean Architecture is to minimize code complexity by preventing implementation complexity.

We must first understand a few things to implement the Clean Architecture in an Android project.

  • Entities: Encapsulate enterprise-wide critical business rules. An entity can be an object with methods or data structures and functions.
  • Use cases: It demonstrates data flow to and from the entities.
  • Controllers, gateways, presenters: A set of adapters that convert data from the use cases and entities format to the most convenient way to pass the data to the upper level (typically the UI).
  • UI, external interfaces, DB, web, devices: The outermost layer of the architecture, generally composed of frameworks such as database and web frameworks.

Here is one thumb rule we need to follow. First, look at the direction of the arrows in the diagram. Entities do not depend on use cases and use cases do not depend on controllers, and so on. A lower-level module should always rely on something other than a higher-level module. The dependencies between the layers must be inwards.

Advantages of Clean Architecture:

  • Strict architecture—hard to make mistakes
  • Business logic is encapsulated, easy to use, and tested
  • Enforcement of dependencies through encapsulation
  • Allows for parallel development
  • Highly scalable
  • Easy to understand and maintain
  • Testing is facilitated

Let’s understand this using the small case study of the Android project, which gives more practical knowledge rather than theoretical.

A pragmatic approach

A typical Android project typically needs to separate the concerns between the UI, the business logic, and the data model, so taking “the theory” into account, we decided to split the project into three modules:

  • Domain Layer: contains the definitions of the business logic of the app, the data models, the abstract definition of repositories, and the definition of the use cases.
Domain Module
Domain Module
  • Data Layer: This layer provides the abstract definition of all the data sources. Any application can reuse this without modifications. It contains repositories and data sources implementations, the database definition and its DAOs, the network APIs definitions, some mappers to convert network API models to database models, and vice versa.
Data Module
  • Presentation layer: This is the layer that mainly interacts with the UI. It's Android-specific and contains fragments, view models, adapters, activities, composable, and so on. It also includes a service locator to manage dependencies.
Presentation Module

Marvel’s comic characters App

To elaborate on all the above concepts related to Clean Architecture, we are creating an app that lists Marvel’s comic characters using Marvel’s developer API. The app shows a list of Marvel characters, and clicking on each character will show details of that character. Users can also bookmark their favorite characters. It seems like nothing complicated, right?

Before proceeding further into the sample, it's good to have an idea of the following frameworks because the example is wholly based on them.

  • Jetpack Compose - Android’s recommended modern toolkit for building native UI.
  • Retrofit 2 - A type-safe HTTP client for Android for Network calls.
  • ViewModel - A class responsible for preparing and managing the data for an activity or a fragment.
  • Kotlin - Kotlin is a cross-platform, statically typed, general-purpose programming language with type inference.

To get a characters list, we have used marvel’s developer API, which returns the list of marvel characters.

http://gateway.marvel.com/v1/public/characters

The domain layer

In the domain layer, we define the data model, the use cases, and the abstract definition of the character repository. The API returns a list of characters, with some info like name, description, and image links.

CODE: https://gist.github.com/velotiotech/74591ab07c3e0baebef18ad634e2d817.js

CODE: https://gist.github.com/velotiotech/8f4bee6dfee70819948fa353c9ca3e93.js

CODE: https://gist.github.com/velotiotech/d79193a0854072d7cb2c7e9f3b25dea8.js

The data layer

As we said before, the data layer must implement the abstract definition of the domain layer, so we need to put the repository's concrete implementation in this layer. To do so, we can define two data sources, a “local” data source to provide persistence and a “remote” data source to fetch the data from the API.

CODE: https://gist.github.com/velotiotech/dd7a188cf77a8b7156ae07f9d3fdb95b.js

Since we defined the data source to manage persistence, in this layer, we also need to determine the database for which we are using the room database. In addition, it’s good practice to create some mappers to map the API response to the corresponding database entity.

CODE: https://gist.github.com/velotiotech/b28ed30775df0935592fa958014cf5b8.js

CODE: https://gist.github.com/velotiotech/8deaf5c35f7c375f40e45717ed3a3344.js

The presentation layer

In this layer, we need a UI component like fragments, activity, or composable to display the list of characters; here, we can use the widely used MVVM approach. The view model takes the use cases in its constructors and invokes the corresponding use case according to user actions (get a character, characters & comics, etc.).

Each use case will invoke the appropriate method in the repository.

CODE: https://gist.github.com/velotiotech/65e35d88a3e6f86837e8777466fd1e8f.js

CODE: https://gist.github.com/velotiotech/43838647680135c3808f409e5f5e1035.js

Let’s see how the communication between the layers looks like.

Source: Clean Architecture Tutorial for Android

As you can see, each layer communicates only with the closest one, keeping inner layers independent from lower layers, this way, we can quickly test each module separately, and the separation of concerns will help developers to collaborate on the different modules of the project.

Thank you so much!

Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

Discover the Benefits of Android Clean Architecture

All architectures have one common goal: to manage the complexity of our application. We may not need to worry about it on a smaller project, but it becomes a lifesaver on larger ones. The purpose of Clean Architecture is to minimize code complexity by preventing implementation complexity.

We must first understand a few things to implement the Clean Architecture in an Android project.

  • Entities: Encapsulate enterprise-wide critical business rules. An entity can be an object with methods or data structures and functions.
  • Use cases: It demonstrates data flow to and from the entities.
  • Controllers, gateways, presenters: A set of adapters that convert data from the use cases and entities format to the most convenient way to pass the data to the upper level (typically the UI).
  • UI, external interfaces, DB, web, devices: The outermost layer of the architecture, generally composed of frameworks such as database and web frameworks.

Here is one thumb rule we need to follow. First, look at the direction of the arrows in the diagram. Entities do not depend on use cases and use cases do not depend on controllers, and so on. A lower-level module should always rely on something other than a higher-level module. The dependencies between the layers must be inwards.

Advantages of Clean Architecture:

  • Strict architecture—hard to make mistakes
  • Business logic is encapsulated, easy to use, and tested
  • Enforcement of dependencies through encapsulation
  • Allows for parallel development
  • Highly scalable
  • Easy to understand and maintain
  • Testing is facilitated

Let’s understand this using the small case study of the Android project, which gives more practical knowledge rather than theoretical.

A pragmatic approach

A typical Android project typically needs to separate the concerns between the UI, the business logic, and the data model, so taking “the theory” into account, we decided to split the project into three modules:

  • Domain Layer: contains the definitions of the business logic of the app, the data models, the abstract definition of repositories, and the definition of the use cases.
Domain Module
Domain Module
  • Data Layer: This layer provides the abstract definition of all the data sources. Any application can reuse this without modifications. It contains repositories and data sources implementations, the database definition and its DAOs, the network APIs definitions, some mappers to convert network API models to database models, and vice versa.
Data Module
  • Presentation layer: This is the layer that mainly interacts with the UI. It's Android-specific and contains fragments, view models, adapters, activities, composable, and so on. It also includes a service locator to manage dependencies.
Presentation Module

Marvel’s comic characters App

To elaborate on all the above concepts related to Clean Architecture, we are creating an app that lists Marvel’s comic characters using Marvel’s developer API. The app shows a list of Marvel characters, and clicking on each character will show details of that character. Users can also bookmark their favorite characters. It seems like nothing complicated, right?

Before proceeding further into the sample, it's good to have an idea of the following frameworks because the example is wholly based on them.

  • Jetpack Compose - Android’s recommended modern toolkit for building native UI.
  • Retrofit 2 - A type-safe HTTP client for Android for Network calls.
  • ViewModel - A class responsible for preparing and managing the data for an activity or a fragment.
  • Kotlin - Kotlin is a cross-platform, statically typed, general-purpose programming language with type inference.

To get a characters list, we have used marvel’s developer API, which returns the list of marvel characters.

http://gateway.marvel.com/v1/public/characters

The domain layer

In the domain layer, we define the data model, the use cases, and the abstract definition of the character repository. The API returns a list of characters, with some info like name, description, and image links.

CODE: https://gist.github.com/velotiotech/74591ab07c3e0baebef18ad634e2d817.js

CODE: https://gist.github.com/velotiotech/8f4bee6dfee70819948fa353c9ca3e93.js

CODE: https://gist.github.com/velotiotech/d79193a0854072d7cb2c7e9f3b25dea8.js

The data layer

As we said before, the data layer must implement the abstract definition of the domain layer, so we need to put the repository's concrete implementation in this layer. To do so, we can define two data sources, a “local” data source to provide persistence and a “remote” data source to fetch the data from the API.

CODE: https://gist.github.com/velotiotech/dd7a188cf77a8b7156ae07f9d3fdb95b.js

Since we defined the data source to manage persistence, in this layer, we also need to determine the database for which we are using the room database. In addition, it’s good practice to create some mappers to map the API response to the corresponding database entity.

CODE: https://gist.github.com/velotiotech/b28ed30775df0935592fa958014cf5b8.js

CODE: https://gist.github.com/velotiotech/8deaf5c35f7c375f40e45717ed3a3344.js

The presentation layer

In this layer, we need a UI component like fragments, activity, or composable to display the list of characters; here, we can use the widely used MVVM approach. The view model takes the use cases in its constructors and invokes the corresponding use case according to user actions (get a character, characters & comics, etc.).

Each use case will invoke the appropriate method in the repository.

CODE: https://gist.github.com/velotiotech/65e35d88a3e6f86837e8777466fd1e8f.js

CODE: https://gist.github.com/velotiotech/43838647680135c3808f409e5f5e1035.js

Let’s see how the communication between the layers looks like.

Source: Clean Architecture Tutorial for Android

As you can see, each layer communicates only with the closest one, keeping inner layers independent from lower layers, this way, we can quickly test each module separately, and the separation of concerns will help developers to collaborate on the different modules of the project.

Thank you so much!

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings