Skip to content

preetanshumishra/PatternKitAndroidMvvmCleanCompose

Repository files navigation

PatternKit — MVVM + Clean Architecture (Jetpack Compose)

Part of PatternKit, a side-by-side reference codebase where the same small Tasks CRUD app is implemented once per architecture pattern across iOS and Android. Every module ships identical behaviour — the same domain model, the same three screens, the same mock data layer — so the only thing that varies is the architecture itself.

This module is the MVVM + Clean Architecture flavour on Jetpack Compose — the production sweet spot Google demonstrates in Now in Android. It interposes a domain layer of use cases between the ViewModels and the repository: ViewModels depend on use cases, use cases depend on the repository contract, and the data layer is the only place that knows about the concrete implementation.

Stack

  • Language: Kotlin
  • UI: Jetpack Compose + Material 3
  • Architecture: MVVM + Clean (Data / Domain / UI layers)
  • DI: Dagger 2 (KSP) — plain Dagger, no Hilt
  • Navigation: Navigation Compose
  • Min SDK: 28 · Target/Compile SDK: 36
  • Package: com.preetanshumishra.patternkit.android.mvvmcleancompose

The Tasks feature

A single-user task list. One entity (TaskItem: title, optional notes, optional due date, priority, completion). Three screens:

  1. List — filter chips (All / Active / Completed), sort by due date or priority, swipe-to-delete, FAB to create.
  2. Detail — read-only fields, toggle completion, edit, delete.
  3. Form — create or edit (mode-driven), title validation (≤ 80 chars), due-date validation (not in the past), 600 ms mock async save.

Data comes from MockTaskRepository — an in-memory store seeded with ~12 tasks, with configurable artificial latency and failure rate. No real network, no local persistence — intentionally, so the architecture stays the focus.

The domain layer (what makes this "Clean")

Five single-responsibility use cases sit between the UI and the data layer:

  • GetTasksUseCase, CreateTaskUseCase, UpdateTaskUseCase, DeleteTaskUseCase, ToggleTaskCompletionUseCase

Each is @Inject constructor-built and depends only on the TaskRepository contract (which lives in domain/, not data/). ViewModels never touch the repository directly — they compose use cases. This is the one structural difference from the plain-MVVM module.

Dependency injection

Plain Dagger 2, wired by hand:

  • AppComponent (@Singleton) exposes the five use cases; RepositoryModule @Binds TaskRepositoryMockTaskRepository.
  • Use cases and the repository are constructor-injected, so Dagger builds them with no @Provides boilerplate.
  • PatternKitApp creates and holds the component; a hand-rolled ViewModelFactory pulls use cases out of the graph and constructs each ViewModel.

Project layout

app/src/main/kotlin/.../mvvmclean/
├── data/        # MockTaskRepository, seed data
├── domain/      # TaskItem, Priority, TaskRepository (contract), UseCases
├── di/          # AppComponent, RepositoryModule
├── ui/
│   ├── list/    # TaskListScreen + TaskListViewModel
│   ├── detail/  # TaskDetailScreen
│   ├── form/    # TaskFormScreen + TaskFormViewModel
│   ├── nav/     # NavHost + Routes
│   ├── theme/   # Material 3 theme
│   └── ViewModelFactory.kt
└── PatternKitApp.kt

Build & run

./gradlew assembleDebug      # build the debug APK
./gradlew installDebug       # install on a connected device/emulator
./gradlew test               # unit tests

Or open the project in Android Studio and run the app configuration.

About

Tasks CRUD reference app built with Jetpack Compose, MVVM and Clean Architecture (domain/data/ui) with Dagger. Part of PatternKit, a side-by-side comparison of mobile architecture patterns.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages