Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Commerce Android Compose

A modern e-commerce Android application built with Kotlin, Jetpack Compose, and Clean Architecture.

Tech Stack

Category Technology
Language Kotlin
UI Jetpack Compose, Material 3
Architecture Clean Architecture + MVVM + MVI
DI Hilt
Networking Retrofit, OkHttp, Kotlinx Serialization
Local Database Room
Local Preferences DataStore
Image Loading Coil
Pagination Paging 3
Navigation Navigation Compose
Async Coroutines + Flow
Testing JUnit 5, MockK, Turbine, Compose UI Test

Architecture

The project follows the official Android architecture guidelines with a multi-module Clean Architecture approach.

Layer Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              APP LAYER                                   β”‚
β”‚   App (@HiltAndroidApp) β†’ MainActivity β†’ NavHost β†’ Feature Screens      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          FEATURE LAYER (MVVM + MVI)                      β”‚
β”‚   Screen (Compose) ←→ ViewModel (MVI) ←→ Contract (State/Event/Effect) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          DOMAIN LAYER (Pure Kotlin)                      β”‚
β”‚   Use Cases β†’ Repository Interfaces β†’ Domain Models                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           DATA LAYER                                     β”‚
β”‚   Repository Impl β†’ Mappers β†’ Remote API (Retrofit) + Local DB (Room)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    CORE LAYER (Shared Infrastructure)                     β”‚
β”‚   common  network  database  datastore  designsystem                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Module Dependency Graph

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚         app          β”‚
                    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚      β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      └────────────┐
              v                                 v
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚   feature/*      β”‚ ──────────►  β”‚     domain       β”‚
    β”‚ (auth, home,     β”‚              β”‚ (use cases,      β”‚
    β”‚  product, cart,  β”‚              β”‚  models,         β”‚
    β”‚  profile)        β”‚              β”‚  interfaces)     β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚                                 β”‚
             └──────────┐             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        v             v
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
               β”‚           data             β”‚
               β”‚ (repo impl, DTOs, DAOs,    β”‚
               β”‚  mappers)                  β”‚
               β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚      β”‚      β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”˜      β”‚      └────────┐
              v              v               v
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β”‚common    β”‚  β”‚network     β”‚  β”‚database      β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                           β”‚
              └──────┐           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     v           v
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚datastore     β”‚  β”‚designsystem     β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Module Responsibilities

app

The application entry point. Hosts MainActivity, global NavHost, bottom navigation, and top-level Hilt modules (AppModule, NetworkModule).

core/common

Shared utilities, Kotlin extensions (ContextExt, FlowExt, StringExt, DateExt), resource wrappers (Resource<T>, UiEvent), and constants.

core/network

Retrofit + OkHttp infrastructure. Provides configured HTTP client, auth and logging interceptors, and a NetworkResult<T> call adapter for type-safe API responses.

core/database

Room database setup. Declares the CommerceDatabase abstract class with all DAOs. Includes type converters and the Hilt module that provides the database instance.

core/datastore

DataStore-backed user preferences (auth token, theme selection, onboarding state). Exposes reactive Flow reads and one-shot suspend writes.

core/designsystem

Material 3 design system. Defines the app theme (CommerceTheme), palette, typography, shapes, and reusable component library (CommerceButton, CommerceTextField, CommerceCard, ErrorView, LoadingIndicator, etc.).

domain (Pure Kotlin β€” no Android dependencies)

The innermost layer containing business logic. Defines domain models, repository interfaces, and use cases. Has zero framework dependencies β€” no Hilt, no Retrofit, no Room.

data

Implements repository interfaces from the domain layer. Orchestrates remote API calls (Retrofit) and local persistence (Room). Contains DTOs, entities, mappers for data transformation, and the DI module that binds implementations to interfaces.

feature/auth

Authentication flow: login, registration. MVI pattern with AuthContract (State/Event/Effect), AuthViewModel, and Compose screens.

feature/home

Home dashboard: banner carousel, category grid, recommended product rows.

feature/product

Product browsing: paginated list with filtering/sorting via Paging 3, and product detail page with image gallery.

feature/cart

Shopping cart: cart items list, quantity adjustment, checkout screen. Supports offline cart persistence.

feature/profile

User profile: profile display/edit, order history, app settings (theme, notifications, logout).

MVI Architecture Pattern

Each feature follows a consistent MVI contract pattern:

FeatureContract.kt
β”œβ”€β”€ data class FeatureUiState        β€” Immutable state snapshot
β”œβ”€β”€ sealed interface FeatureUiEvent  β€” User intents (click, scroll, type)
└── sealed interface FeatureSideEffect β€” One-shot effects (snackbar, navigation)

The ViewModel:

  1. Receives UiEvents from the UI
  2. Reduces them into new UiState via StateFlow
  3. Emits one-shot SideEffects via a shared Channel<SideEffect> β†’ Flow

Project Structure

CommerceAndroidCompose/
β”œβ”€β”€ app/
β”œβ”€β”€ core/
β”‚   β”œβ”€β”€ common/
β”‚   β”œβ”€β”€ network/
β”‚   β”œβ”€β”€ database/
β”‚   β”œβ”€β”€ datastore/
β”‚   └── designsystem/
β”œβ”€β”€ data/
β”œβ”€β”€ domain/
└── feature/
    β”œβ”€β”€ auth/
    β”œβ”€β”€ home/
    β”œβ”€β”€ product/
    β”œβ”€β”€ cart/
    └── profile/

Each module follows the package convention com.example.commerce.<module>.

Getting Started

  1. Clone the repository

    git clone <repo-url>
  2. Open in Android Studio β€” Use File β†’ Open and select the project root.

  3. Sync dependencies

    ./gradlew build
  4. Run Select the app configuration and run on a device/emulator (API 26+).

Build Variants

Variant Description
debug Development, logging enabled
release Optimized, no logging

Testing

Unit Tests

  • JUnit 5 for test execution
  • MockK for mocking
  • Turbine for testing Kotlin Flows
  • Location: src/test/ in each module

UI Tests

  • Compose UI Test for Compose screen interaction
  • Espresso for supplemental UI assertions
  • Location: src/androidTest/ in feature modules
# Run all tests
./gradlew test

# Run all instrumented tests
./gradlew connectedAndroidTest

Dependencies

Dependency versions are managed centrally in gradle/libs.versions.toml (Gradle Version Catalog).

Key libraries:

  • AndroidX: Core KTX, Activity Compose, Lifecycle, Navigation
  • Compose: BOM, Material 3, UI, Tooling
  • Hilt: DI, ViewModel injection, Navigation
  • Retrofit: HTTP client, Kotlinx Serialization converter
  • Room: Database, Coroutines support
  • DataStore: Preferences, Proto DataStore
  • Paging 3: Compose integration
  • Coil: Async image loading
  • Testing: JUnit 5, MockK, Turbine, Compose UI Test

Architecture Decision Records

Why Clean Architecture + Multi-Module?

  • Separation of concerns: Business logic is isolated from framework details
  • Testability: Domain layer is pure Kotlin β€” trivial to unit test
  • Scalability: Feature modules can be developed independently
  • Build time: Gradle parallelizes module builds; incremental changes are faster

Why MVI over MVVM?

  • Unidirectional data flow β€” state is predictable and debuggable
  • Immutable state β€” no accidental mutations
  • Side effect channel β€” one-shot events (navigation, snackbar) don't survive configuration changes incorrectly

Why a single data module instead of per-feature data modules?

  • Shared caching policies, offline-first logic, and cross-feature data access are easier with a unified data layer
  • Simpler DI graph β€” one RepositoryModule instead of one per feature
  • Avoids circular dependencies between feature data layers

License

Copyright 2026

Licensed under the Apache License, Version 2.0 ...

About

A modern e-commerce Android application built with Kotlin, Jetpack Compose, and Clean Architecture.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages