Skip to main content

Overview

The android-architecture skill provides expert guidance on structuring Android applications using modern architecture patterns. It focuses on Clean Architecture principles, proper layering, Hilt dependency injection, and modularization strategies for production apps. When to use this skill:
  • Setting up new Android projects
  • Refactoring existing apps to modern architecture
  • Implementing dependency injection with Hilt
  • Designing multi-module project structures
  • Establishing clear separation of concerns

High-Level Architecture Layers

The architecture is structured into three primary layers with strict dependency rules: dependencies must flow inwards (or downwards) toward the core logic.
Responsibility: Displaying data and handling user interactionsComponents:
  • Activities
  • Fragments
  • Composables
  • ViewModels
Dependencies: Depends on the Domain Layer (or Data Layer if simple). Never depends on Data Layer implementation details directly.
Responsibility: Managing application data (fetching, caching, saving)Components:
  • Repositories (implementations)
  • Data Sources (Retrofit APIs, Room DAOs)
Dependencies: Depends only on external sources and libraries

Dependency Injection with Hilt

Use Hilt for all dependency injection in your Android app.

Application Setup

@HiltAndroidApp
class MyApplication : Application() {
    // Application initialization
}

Activity and Fragment Injection

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    // Hilt will inject dependencies
}

@AndroidEntryPoint
class MyFragment : Fragment() {
    // Hilt will inject dependencies
}

ViewModel Injection

@HiltViewModel
class NewsViewModel @Inject constructor(
    private val getNewsUseCase: GetNewsUseCase
) : ViewModel() {
    // ViewModel implementation
}

Hilt Modules

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
    @Provides
    @Singleton
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com")
            .build()
    }
}
Use @Binds in an abstract class to bind interface implementations - it’s cleaner and more efficient than @Provides.

Modularization Strategy

For production apps, use a multi-module strategy to improve build times and separation of concerns.
:app
├── :core
│   ├── :model      (Shared domain models - Pure Kotlin)
│   ├── :data       (Repositories, Data Sources, Database, Network)
│   ├── :domain     (Use Cases and Repository Interfaces)
│   └── :ui         (Shared Composables, Theme, Resources)
└── :feature
    ├── :news       (News feature UI and ViewModels)
    ├── :profile    (Profile feature UI and ViewModels)
    └── :settings   (Settings feature UI and ViewModels)

Module Responsibilities

:app

Main entry point that connects features together

: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 features with UI and ViewModels. Depends on :core:domain and :core:ui

Implementation Checklist

1

Ensure Pure Domain Layer

Verify that the Domain layer has no Android dependencies - it should be pure Kotlin only
2

Main-Safe Repository Functions

Repositories should default to main-safe suspend functions (use Dispatchers.IO internally if needed)
3

StateFlow for UI Communication

ViewModels should interact with the UI layer via StateFlow (see android-viewmodel)

Best Practices

Never let the UI Layer depend on Data Layer implementation details directly. Always go through the Domain Layer or use Repository interfaces.
  • Keep the Domain Layer pure Kotlin with no Android framework dependencies
  • Use Hilt for all dependency injection
  • Follow the dependency rule: dependencies flow inward/downward
  • Modularize production apps for better build times and separation
  • Use @Binds for interface binding in Hilt modules

ViewModel & State

Learn how to implement ViewModels with StateFlow and SharedFlow

Data Layer

Implement the Repository pattern with Room and Retrofit

Build docs developers (and LLMs) love