When designing or refactoring an Android application, adhere to the
Guide to App Architecture
and
Clean Architecture
principles.
1. High-Level Layers
Structure the application into three primary layers. Dependencies must strictly flow
inwards
(or downwards) to the core logic.
UI Layer (Presentation)
:
Responsibility
Displaying data and handling user interactions.
Components
Activities, Fragments, Composables, ViewModels.
Dependencies
Depends on the Domain Layer (or Data Layer if simple).
Never
depends on the Data Layer implementation details directly.
Domain Layer (Business Logic) [Optional but Recommended]
:
Responsibility
Encapsulating complex business rules and reuse.
Components
Use Cases (e.g.,
GetLatestNewsUseCase
), Domain Models (pure Kotlin data classes).
Pure Kotlin
Must NOT contain any Android framework dependencies (no
android.*
imports).
Dependencies
Depends on Repository Interfaces.
Data Layer
:
Responsibility
Managing application data (fetching, caching, saving).
Components
Repositories (implementations), Data Sources (Retrofit APIs, Room DAOs).
Dependencies
Depends only on external sources and libraries.
2. Dependency Injection with Hilt
Use
Hilt
for all dependency injection.
@HiltAndroidApp
Annotate the
Application
class.
@AndroidEntryPoint
Annotate Activities and Fragments.
@HiltViewModel
Annotate ViewModels; use standard
constructor
injection.
Modules
:
Use
@Module
and
@InstallIn(SingletonComponent::class)
for app-wide singletons (e.g., Network, Database).
Use
@Binds
in an abstract class to bind interface implementations (cleaner than
@Provides
).
3. Modularization Strategy
For production apps, use a multi-module strategy to improve build times and separation of concerns.
:app
The main entry point, connects features.
:core:model
Shared domain models (Pure Kotlin).
:core:data
Repositories, Data Sources, Database, Network.
:core:domain
Use Cases and Repository Interfaces.
:core:ui
Shared Composables, Theme, Resources.
:feature:[name]
Standalone feature modules containing their own UI and ViewModels. Depends on
:core:domain
and
:core:ui
.
4. Checklist for implementation
Ensure
Domain
layer has no Android dependencies.
Repositories should default to main-safe suspend functions (use
Dispatchers.IO
internally if needed).
ViewModels should interact with the UI layer via
StateFlow
(see
android-viewmodel
skill).