Skip to content

issu321/Android-Todo-App

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MyApp — Android Task Manager

A production-grade Android application built with Kotlin, Jetpack Compose, Material Design 3, and Clean Architecture. This project serves as a scalable template for modern Android development.


Table of Contents


Tech Stack

Technology Version Purpose
Kotlin 2.0.21 Primary language
Jetpack Compose BOM 2025.06 Declarative UI
Material Design 3 Latest UI components & theming
Hilt 2.52 Dependency injection
Room 2.6.1 Local SQLite database
Retrofit 2.11.0 REST API client
OkHttp 4.12.0 HTTP client + logging
Coroutines 1.9.0 Asynchronous programming
Compose Navigation 2.8.5 In-app navigation
KSP 2.0.21-1.0.28 Annotation processing
AGP 8.7.0 Android Gradle Plugin
compileSdk 35 Target Android API
minSdk 26 Android 8.0+ support

Architecture

This project follows Clean Architecture with MVVM pattern:

Presentation Layer (UI + ViewModel)
        ↓
Domain Layer (Use Cases + Repository Interface + Models)
        ↓
Data Layer (RepositoryImpl + Room DAO + Retrofit API)
        ↓
Local DB  ←——→  Remote API

Key Principles

  • Single Source of Truth: Room database is the authoritative data source
  • Reactive UI: All reads return Flow<T> — Compose auto-recomposes on data changes
  • Separation of Concerns: UI, business logic, and data access are strictly separated
  • Dependency Inversion: Domain layer depends on abstractions, not implementations
  • Error Handling: Result<T> sealed class encapsulates Loading/Success/Error states

Project Structure

com.ussu321.template/
│
├── core/                          # Scalable foundation layer
│   ├── network/
│   │   └── ApiResult.kt           # Generic API result wrapper + safeApiCall()
│   ├── dispatcher/
│   │   └── CoroutineDispatcherModule.kt  # Injectable dispatchers (@IoDispatcher, etc.)
│   ├── errors/
│   │   ├── AppException.kt        # Typed exception hierarchy
│   │   └── ErrorMapper.kt         # Throwable → AppException + UI string mapping
│   └── extensions/
│       ├── ContextExt.kt          # toast(), toastLong()
│       ├── FlowExt.kt             # Flow<T>.asResult()
│       ├── DateExt.kt             # Long.toFormattedDate(), Long.toRelativeDate()
│       └── StringExt.kt           # ifBlankOrNull(), truncate()
│
├── common/                        # Reusable UI building blocks
│   ├── loading/
│   │   ├── LoadingIndicator.kt    # Centered circular progress
│   │   ├── FullScreenLoading.kt   # Scrim overlay with spinner
│   │   └── ShimmerLoading.kt      # Animated shimmer skeleton
│   ├── dialogs/
│   │   ├── ConfirmationDialog.kt  # Reusable confirm/dismiss dialog
│   │   └── InfoDialog.kt          # Single-button info dialog
│   ├── widgets/
│   │   ├── Spacers.kt             # Consistent spacing composables
│   │   └── AppLogo.kt             # Standardized icon wrapper
│   └── animations/
│       ├── FadeIn.kt              # Fade animation wrapper
│       ├── SlideIn.kt             # Vertical slide animation
│       └── ScaleIn.kt             # Scale animation wrapper
│
├── data/                          # Data layer
│   ├── local/
│   │   ├── AppDatabase.kt         # Room database singleton
│   │   └── TaskDao.kt             # Data Access Object for tasks
│   ├── model/
│   │   └── TaskEntity.kt          # Room entity
│   ├── remote/
│   │   ├── TaskApiService.kt      # Retrofit API interface
│   │   ├── dto/
│   │   │   └── TaskDto.kt         # JSON data transfer object
│   │   └── mapper/
│   │       ├── TaskDtoMapper.kt   # DTO ↔ Entity, DTO ↔ Domain mappings
│   │       └── TaskEntityMapper.kt # Entity ↔ Domain mappings
│   └── repository/
│       └── TaskRepositoryImpl.kt  # Concrete repository implementation
│
├── domain/                        # Domain layer (framework-independent)
│   ├── model/
│   │   ├── Result.kt              # Sealed class: Loading/Success/Error
│   │   └── Task.kt                # Domain model
│   ├── repository/
│   │   └── TaskRepository.kt      # Repository interface contract
│   └── usecase/
│       ├── GetAllTasksUseCase.kt
│       ├── GetTaskByIdUseCase.kt
│       ├── AddTaskUseCase.kt
│       ├── UpdateTaskUseCase.kt
│       ├── DeleteTaskUseCase.kt
│       ├── ToggleTaskCompletionUseCase.kt
│       └── GetActiveTaskCountUseCase.kt
│
├── di/
│   └── AppModule.kt               # Hilt dependency providers
│
├── ui/                            # Presentation layer
│   ├── theme/
│   │   ├── Color.kt               # Light/dark color palettes
│   │   ├── Theme.kt               # Dynamic color + system bar theming
│   │   └── Type.kt                # Material 3 typography scale
│   ├── navigation/
│   │   ├── Screen.kt              # Type-safe route definitions
│   │   └── AppNavigation.kt       # NavHost with navigation graph
│   ├── components/
│   │   ├── TaskCard.kt            # Task list item card
│   │   ├── PriorityChip.kt        # Priority level indicator chip
│   │   ├── EmptyState.kt          # Empty list illustration
│   │   └── AddTaskDialog.kt       # Task creation dialog
│   └── screens/
│       ├── home/
│       │   └── HomeScreen.kt      # Main task list screen
│       └── detail/
│           └── TaskDetailScreen.kt # Task detail view
│
├── viewmodel/
│   ├── HomeViewModel.kt           # Home screen state management
│   └── TaskDetailViewModel.kt     # Detail screen state management
│
├── utils/
│   └── Constants.kt               # App-wide constants
│
├── MainActivity.kt                # Entry point with edge-to-edge
└── MyApplication.kt               # @HiltAndroidApp application class

Prerequisites

  • Android Studio Koala or Quail (2026.x) or later
  • JDK 17 or higher
  • Android SDK with API 35 installed
  • Git (optional, for version control)

Getting Started

1. Clone or Extract the Project

# If using Git
git clone <repository-url>
cd MyApp

# Or extract the ZIP file and open the `android_project/` folder

2. Open in Android Studio

  1. Launch Android Studio
  2. Select "Open" and choose the android_project/ directory
  3. Wait for Gradle sync to complete (may take 2–5 minutes on first open)

3. Build the Project

# Via Android Studio: Build → Make Project (Ctrl+F9)
# Or via terminal:
./gradlew assembleDebug

4. Run on Device or Emulator

  • Physical device: Enable USB debugging, connect via USB, select device in Android Studio
  • Emulator: Create an AVD with API 26+ (recommend API 33+ for best experience)
  • Click Run (Shift+F10) or use the green play button

Features

Current Features

Feature Description
✅ Task List View all tasks sorted by priority and creation time
✅ Add Task Create tasks with title, description, and priority (Low/Medium/High)
✅ Task Detail View full task information including creation date
✅ Toggle Completion Mark tasks as completed/incomplete with checkbox
✅ Delete Task Remove tasks with confirmation dialog
✅ Empty State Friendly illustration when no tasks exist
✅ Reactive UI Auto-updates when database changes via Flow
✅ Error Handling Snackbar notifications for operation failures
✅ Material You Dynamic color theming on Android 12+
✅ Dark Mode Automatic light/dark theme switching

Architecture Highlights

Feature Benefit
Extracted Mappers TaskDtoMapper & TaskEntityMapper are testable and reusable
Injectable Dispatchers Easy test substitution with Dispatchers.Unconfined
Typed Exceptions AppException hierarchy enables precise error handling
Safe API Calls safeApiCall() wrapper prevents crashes from network issues
Extension Functions Clean, reusable utilities (toFormattedDate(), asResult())
Reusable Components ConfirmationDialog, ShimmerLoading, Spacer16() reduce duplication

Testing

Unit Tests

# Run all unit tests
./gradlew test

# Run tests for a specific module
./gradlew :app:testDebugUnitTest

Instrumented Tests

# Run instrumented tests on connected device/emulator
./gradlew connectedAndroidTest

Recommended Test Additions

  1. Mapper Tests: Verify TaskDtoMapper and TaskEntityMapper conversions
  2. Repository Tests: Mock TaskDao and TaskApiService to test TaskRepositoryImpl
  3. ViewModel Tests: Use kotlinx-coroutines-test with Dispatchers.Unconfined
  4. UI Tests: Use Compose Testing framework for screen navigation and interactions

Build & Release

Debug Build

./gradlew assembleDebug
# Output: app/build/outputs/apk/debug/app-debug.apk

Release Build

# Requires signing configuration in app/build.gradle.kts
./gradlew assembleRelease
# Output: app/build/outputs/apk/release/app-release.apk

ProGuard/R8

Release builds automatically enable:

  • Code shrinking (isMinifyEnabled = true)
  • Resource shrinking (isShrinkResources = true)
  • ProGuard rules in app/proguard-rules.pro

Customization Guide

Change App Name

Edit app/src/main/res/values/strings.xml:

<string name="app_name">Your App Name</string>

Change Package Name

  1. Refactor com.ussu321.template to your desired package in Android Studio
  2. Update namespace and applicationId in app/build.gradle.kts
  3. Update AndroidManifest.xml if needed

Connect to Real Backend

  1. Update BASE_URL in utils/Constants.kt
  2. Modify TaskApiService.kt endpoints to match your API
  3. Adjust TaskDto fields and TaskDtoMapper if response format differs

Add New Screens

  1. Add route to ui/navigation/Screen.kt
  2. Register in ui/navigation/AppNavigation.kt
  3. Create screen composable in ui/screens/
  4. Create ViewModel in viewmodel/ (if needed)

Add New Database Entities

  1. Create entity in data/model/
  2. Add to AppDatabase.kt @Database(entities = [...])
  3. Create DAO in data/local/
  4. Provide DAO in di/AppModule.kt

Troubleshooting

Issue Solution
Gradle sync fails Check JDK 17 is selected: File → Settings → Build → Gradle
KSP errors Ensure KSP plugin version matches Kotlin version
Room compilation errors Check @Entity and @Dao annotations are correct
Hilt injection fails Verify @HiltAndroidApp on MyApplication and @AndroidEntryPoint on MainActivity
Compose preview not working Ensure debugImplementation(libs.androidx.ui.tooling) is present

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Commit changes: git commit -m "Add my feature"
  4. Push to branch: git push origin feature/my-feature
  5. Open a Pull Request

License

Copyright 2026 ussu321

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Acknowledgments


Built with ❤️ using Kotlin, Jetpack Compose, and Clean Architecture.

About

A production-grade Android application built with Kotlin, Jetpack Compose, Material Design 3, and Clean Architecture. This project serves as a scalable template for modern Android development.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages