Android Core

Clean Architecture in Android — Complete Guide

1. What is Clean Architecture?

Clean Architecture is a design pattern proposed by Robert C. Martin (Uncle Bob) that emphasizes **separation of concerns**, **testability**, and **maintainability**. It divides the codebase into layers where dependencies always point **inward**, ensuring that core business logic is independent of frameworks, UI, or external systems.

2. Core Layers of Clean Architecture

  • Entities: Encapsulate the core business rules. They are independent of frameworks and external dependencies.
  • Use Cases / Interactors: Contain application-specific business rules. They orchestrate the flow of data to and from the Entities.
  • Interface Adapters / Presenters: Convert data from the use cases into a form suitable for the UI, database, or external services.
  • Frameworks & Drivers: Outer layer containing Android SDK, databases, network libraries, and UI components (Compose or XML).

3. Key Principles

  • Dependency Rule: Source code dependencies always point inward, never outward.
  • Separation of Concerns: Each layer has a single responsibility and does not rely on outer layers.
  • Testability: Core business logic can be tested independently of the Android framework.

4. Advantages of Clean Architecture

  • Highly maintainable and scalable for large apps.
  • Easy to test core business logic.
  • Allows swapping frameworks or UI without affecting business rules.
  • Decouples UI, data, and business logic effectively.

5. Example: Simple Login Feature Using Clean Architecture

📁 Folder Structure


                    ├── domain/
                    │   ├── model/User.kt
                    │   └── usecase/LoginUseCase.kt
                    ├── data/
                    │   ├── repository/UserRepositoryImpl.kt
                    │   └── source/UserDataSource.kt
                    ├── presentation/
                    │   ├── view/LoginActivity.kt
                    │   └── viewmodel/LoginViewModel.kt
                    └── di/
                        └── AppModule.kt
                    

🧩 Domain Layer — Entities & Use Case


            // User Entity
            package com.example.cleanarchitecture.domain.model

            data class User(val username: String, val password: String) {
                fun isValid(): Boolean = username.isNotEmpty() && password.length >= 6
            }

            // Login Use Case
            package com.example.cleanarchitecture.domain.usecase

            import com.example.cleanarchitecture.domain.model.User
            import com.example.cleanarchitecture.domain.repository.UserRepository

            class LoginUseCase(private val repository: UserRepository) {
                fun execute(username: String, password: String): Boolean {
                    val user = User(username, password)
                    return if (user.isValid()) repository.login(user) else false
                }
            }
                    

📦 Data Layer — Repository & Data Source


            package com.example.cleanarchitecture.data.repository

            import com.example.cleanarchitecture.domain.model.User
            import com.example.cleanarchitecture.domain.repository.UserRepository
            import com.example.cleanarchitecture.data.source.UserDataSource

            class UserRepositoryImpl(private val dataSource: UserDataSource) : UserRepository {
                override fun login(user: User): Boolean {
                    return dataSource.login(user)
                }
            }

            // Simulated Data Source
            package com.example.cleanarchitecture.data.source

            import com.example.cleanarchitecture.domain.model.User

            class UserDataSource {
                fun login(user: User): Boolean {
                    // Simulate authentication
                    return user.username == "admin" && user.password == "123456"
                }
            }
                    

🖥️ Presentation Layer — ViewModel & Activity


            package com.example.cleanarchitecture.presentation.viewmodel

            import androidx.lifecycle.LiveData
            import androidx.lifecycle.MutableLiveData
            import androidx.lifecycle.ViewModel
            import com.example.cleanarchitecture.domain.usecase.LoginUseCase

            class LoginViewModel(private val loginUseCase: LoginUseCase) : ViewModel() {
                private val _loginResult = MutableLiveData()
                val loginResult: LiveData get() = _loginResult

                fun login(username: String, password: String) {
                    val success = loginUseCase.execute(username, password)
                    _loginResult.value = if (success) "Login Successful" else "Invalid Credentials"
                }
            }

            // Activity (XML or Compose)
            package com.example.cleanarchitecture.presentation.view

            import android.os.Bundle
            import android.widget.Toast
            import androidx.activity.viewModels
            import androidx.appcompat.app.AppCompatActivity
            import com.example.cleanarchitecture.presentation.viewmodel.LoginViewModel

            class LoginActivity : AppCompatActivity() {
                private val viewModel: LoginViewModel by viewModels() 

                override fun onCreate(savedInstanceState: Bundle?) {
                    super.onCreate(savedInstanceState)
                    // setContentView(R.layout.activity_login)

                    viewModel.loginResult.observe(this) { message ->
                        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
                    }

                    // On button click:
                    // viewModel.login(username, password)
                }
            }
                    

6. Summary

  • Clean Architecture separates code into layers: Domain → Data → Presentation → Framework.
  • Dependencies always point inward, making the core business logic independent of Android frameworks.
  • Highly maintainable, testable, and scalable for large projects.
  • Works perfectly with MVVM or MVI in the Presentation layer.

Conclusion

Clean Architecture is the gold standard for professional Android applications. It ensures a clean separation between business logic, data, and UI, allowing for easier testing, maintenance, and future-proofing of your app. This architecture is highly favored in CTO-level interviews.