Clean Architecture Tutorial for Android: Getting Started
- Getting Started
- Clean Architecture
- Why Architecture Is Important
- SOLID Principles
- Layers of Clean Architecture
- Project Structure
- The Data and Business Logic Layers
- The Domain Layer
- The Data Layer
- Adding Repositories
- The Use Cases Layer
- Adding The Remaining Use Cases
- Framework and UI
- The Framework Layer
- Adding Remaining Data Sources
- The Presentation Layer
- Using MVVM
- Providing Sources
- Implementing MVVM
- Reading Documents
- Rendering PDFs
- Adding the Library Functionality
- Opening and Bookmarking Documents
- When to Use Clean Architecture
- Where to Go From Here?
Are you looking for a good architecture for complex Android projects? Have you heard about Clean Architecture but don’t know what all the fuss is about?
In this tutorial you’ll learn the basics of Clean Architecture, including:
- Why it’s important to use architecture patterns in software
- What Clean Architecture is
- What SOLID principles of development are
- When to use Clean Architecture and SOLID principles
- How to implement Clean Architecture on Android
There has always been an open debate, on which architectural pattern to use on Android. Since the early days, you got the feeling that things weren’t right, the way they were set up. This, in turn, caused a lot of people to struggle with architecture in general.
However, for quite a long time, there have been talks about writing your applications in a clean way. Furthermore, one of the most influential persons in the global programmer community, Robert C. Martin, also known as Uncle Bob, has written a book, specifically on this topic.
Because the Clean architecture can be used in any application and platform, not just Android, it’s very informative to understand the idea behind it, and why it’s a good solution, for most problems we find nowadays, as programmers. With that in mind, in this tutorial, you’ll learn how to use the Clean architecture pattern to build a Majestic Reader app, a simple PDF reader.
To get started, download the Majestic Reader project using the Download Materials button at the top or bottom of this tutorial. Open the project in Android Studio 3.2 or later by selecting Open an existing Android Studio project on the Android Studio welcome screen:
In case something goes wrong, due to sync issues, simply press the Gradle sync button, and everything should be fine! Finally, build and run the project. You should see that the main screen of the app is currently empty:
The app consists of two screens:
- A list of PDF documents in your library.
- A PDF document reader.
Currently, those are dummy screens. Your job is to implement library and reader functionality using Clean Architecture.
You might be wondering: Why should I use an architecture? I’m better than that. Well, bear with me.
Why Architecture Is Important
All architectures have one common goal — to manage the complexity of your application. You may not need to worry about it on a smaller project, but it becomes a lifesaver on larger ones.
How does Clean Architecture approach the problem?
You might have seen this graph already:
The circles represent different levels of software in your app. There are two key things to note:
- The center circle is the most abstract, and the outer circle is the most concrete. This is called the Abstraction Principle. The Abstraction Principle specifies that inner circles should contain business logic, and outer circles should contain implementation details.
- Another principle of Clean Architecture is the Dependency Rule. This rule specifies that each circle can depend only on the nearest inward circle — this is what makes the architecture work.
The outer circle represents the concrete mechanisms that are specific to the platform such as networking and database access. Moving inward, each circle is more abstract and higher-level. The center circle is the most abstract and contains business logic, which doesn’t rely on the platform or the framework you’re using.
Additional benefits of using an architecture when structuring app code include:
- Parts of the code get decoupled, and easier to reuse and test.
- There’s a method to the madness. When someone else works on your code, they can learn the app’s architecture and will understand it better.
Five design principles make software design more understandable, flexible and maintainable. Those principles are:
- Single Responsibility: Each software component should have only one reason to change – one responsibility.
- Open-closed: You should be able to extend the behavior of a component, without breaking its usage, or modifying its extensions.
- Liskov Substitution: If you have a class of one type, and any subclasses of that class, you should be able to represent the base class usage with the subclass, without breaking the app.
- Interface Segregation: It’s better to have many smaller interfaces than a large one, to prevent the class from implementing the methods that it doesn’t need.
- Dependency Inversion: Components should depend on abstractions rather than concrete implementations. Also higher level modules shouldn’t depend on lower level modules.
Clean Architecture maximizes the use of these principles.
Layers of Clean Architecture
There are different opinions about how many layers Clean Architecture should have. The architecture doesn’t define exact layers but instead lays out the foundation. The idea is that you adapt the number of layers to your needs.
To keep things simple, you’ll use five layers:
- Presentation: A layer that interacts with the UI.
- Use cases: Sometimes called interactors. Defines actions the user can trigger.
- Domain: Contains the business logic of the app.
- Data: Abstract definition of all the data sources.
- Framework: Implements interaction with the Android SDK and provides concrete implementations for the data layer.
Layers marked green depend on Android SDK.
Since Clean architecture can be applied anywhere, it’s important to know how you’ll implement it on Android.
You’ll split the project into two modules:
- The existing app module.
- A new core module that will hold all the code that doesn’t depend on Android SDK.
The following graph shows communication between the layers and how they are arranged in modules:
The app module is already there, so start by creating a core module.
Right click on MajesticReader in Project explorer and select New ▸ Module or select File ▸ New ▸ New Module.
In the wizard, select Java library and click “Next”.
Under Library name, type core.
Click on the Edit button next to the Java package name field and type in com.raywenderlich.android.majesticreader. Then, click Done.
Ignore Java Class Name and click on Finish.
Wait for the gradle to sync. Then, open build.gradle in the core module and add the following after the first apply plugin line:
apply plugin: 'kotlin'
dependencies section, add two more dependencies:
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1"
Next, reference the core module from the app module.
Open build.gradle in the app module and add the following line under the dependencies block:
Click Sync Now in the top-right corner on the message strip and wait for the Gradle to sync.
Next, select com.raywenderlich.adroid.majesticreader in the core module. Right-click and select New ▸ Package
Type in domain for the name of the new package.
Repeat the process and create two more packages: data and interactors.
Feel free to delete the Java class created by the new module wizard. Now, you have to implement each of the layers independently. :]