Oops! Something went wrong while submitting the form.
We use cookies to improve your browsing experience on our website, to show you personalised content and to analize our website traffic. By browsing our website, you consent to our use of cookies. Read privacy policy.
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.
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.
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.
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.
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.
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.
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.
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.
Let’s see how the communication between the layers looks like.
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!
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
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.
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.
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.
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.
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.
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.
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.
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.
Let’s see how the communication between the layers looks like.
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.
Velotio Technologies is an outsourced software product development partner for top technology startups and enterprises. We partner with companies to design, develop, and scale their products. Our work has been featured on TechCrunch, Product Hunt and more.
We have partnered with our customers to built 90+ transformational products in areas of edge computing, customer data platforms, exascale storage, cloud-native platforms, chatbots, clinical trials, healthcare and investment banking.
Since our founding in 2016, our team has completed more than 90 projects with 220+ employees across the following areas:
Building web/mobile applications
Architecting Cloud infrastructure and Data analytics platforms