A production-ready Android application demonstrating modern Android development best practices, including Clean Architecture, MVVM pattern, Jetpack Compose, offline-first approach with Room database, comprehensive testing, and CI/CD.
- ποΈ Clean Architecture - Separation of concerns with clear layer boundaries
- π± MVVM Pattern - Reactive UI with ViewModels and StateFlow
- π¨ Jetpack Compose - Modern declarative UI toolkit
- πΎ Offline-First - Room database with cache-first strategy (5-minute cache timeout)
- π Networking - Retrofit with proper error handling
- π Dependency Injection - Hilt for clean, testable code
- π§ͺ Comprehensive Testing - Unit tests, UI tests, and integration tests (33 tests total)
- π Code Quality - Detekt static analysis with custom rules
- π CI/CD - GitHub Actions for automated testing and builds
- π― Edge-to-Edge UI - Modern Material 3 design with proper window insets
- β‘ Performance - ProGuard/R8 optimization for release builds
- Kotlin 2.3.10
- Min SDK 30 (Android 11)
- Target SDK 36
- Jetpack Compose 2026.02.00 BOM
- Material 3 - Modern Material Design
- Compose Navigation - For multi-screen apps
- Hilt Navigation Compose - ViewModel integration
- Hilt 2.59.2 - Dependency Injection
- Coroutines 1.10.2 - Asynchronous programming
- StateFlow - Reactive state management
- Retrofit 3.0.0 - HTTP client
- Gson - JSON serialization
- OkHttp Logging Interceptor - Network debugging
- Room 2.8.4 - Local persistence
- Room KTX - Coroutines support
- JUnit 4.13.2 - Unit testing framework
- Kotlin Test - Kotlin-specific assertions
- MockK 1.14.9 - Mocking library
- Turbine 1.2.1 - Flow testing
- Coroutines Test - Coroutine testing utilities
- Compose UI Test - UI testing
- Hilt Testing - DI testing support
- Detekt 1.23.8 - Static code analysis
- KSP 2.3.4 - Annotation processing
This project follows Clean Architecture principles with three main layers:
βββββββββββββββββββββββββββββββββββββββββββ
β Presentation Layer β
β - UI (Compose) β
β - ViewModels β
β - UI State β
βββββββββββββββββββββββββββββββββββββββββββ
β β
βββββββββββββββββββββββββββββββββββββββββββ
β Domain Layer β
β - Use Cases β
β - Domain Models β
β - Repository Interfaces β
βββββββββββββββββββββββββββββββββββββββββββ
β β
βββββββββββββββββββββββββββββββββββββββββββ
β Data Layer β
β - Repository Implementations β
β - Local Database (Room) β
β - Remote API (Retrofit) β
βββββββββββββββββββββββββββββββββββββββββββ
app/src/main/java/io/codetheworld/uitestdemo/
βββ core/
β βββ di/ # Dependency injection modules
β β βββ AppModule.kt
β β βββ DatabaseModule.kt
β β βββ NetworkModule.kt
β βββ network/ # Network utilities
β βββ ApiService.kt
β βββ NetworkConstants.kt
β βββ NetworkResult.kt
βββ data/
β βββ local/ # Room database
β β βββ AppDatabase.kt
β β βββ dao/
β β β βββ PostDao.kt
β β βββ entity/
β β βββ PostEntity.kt
β βββ repository/ # Repository implementations
β βββ PostRepositoryImpl.kt
βββ domain/
β βββ model/ # Domain models
β β βββ Post.kt
β βββ repository/ # Repository interfaces
β β βββ PostRepository.kt
β βββ usecase/ # Business logic
β βββ GetPostsUseCase.kt
βββ ui/
βββ post/ # Post feature
β βββ PostScreen.kt
β βββ PostUiState.kt
β βββ PostViewModel.kt
β βββ UiError.kt
βββ theme/ # App theming
βββ Color.kt
βββ Theme.kt
βββ Type.kt
- Android Studio Ladybug | 2024.2.1 or later
- JDK 17 or later
- Android SDK 36
- Gradle 9.2.1
- Clone the repository
git clone https://github.com/yourusername/UITestDemo.git
cd UITestDemo-
Open the project in Android Studio
-
Sync Gradle files
-
Run the app
./gradlew assembleDebugUnit Tests:
./gradlew testUI Tests:
./gradlew connectedAndroidTestCode Quality Check:
./gradlew detektAll Quality Checks:
./gradlew test detekt assembleDebugThe project includes comprehensive testing:
-
Unit Tests (27 tests)
- ViewModel tests with Turbine
- Repository tests with MockK
- Use case tests
- Error mapping tests
-
UI Tests (3 tests)
- Compose UI tests
- Hilt integration tests
- End-to-end flows
-
Integration Tests
- Repository with fake dependencies
Test Coverage: ~85%
ViewModel Test:
@Test
fun `init loads posts successfully`() = runTest {
// Given
coEvery { getPostsUseCase() } returns NetworkResult.Success(testPosts)
// When
viewModel = PostViewModel(getPostsUseCase)
testDispatcher.scheduler.advanceUntilIdle()
// Then
viewModel.uiState.test {
val state = awaitItem()
assertFalse(state.isLoading)
assertEquals(testPosts, state.posts)
}
}The app implements a cache-first strategy:
- Check local cache first - Always try to serve from cache
- Validate cache - Check if cache is fresh (< 5 minutes)
- Return valid cache immediately - No network call needed
- Fetch on stale/empty - Only call network if necessary
- Fallback to cache - On network errors, return stale cache
Benefits:
- β‘ Instant app startup
- π΄ Works offline
- π Reduced battery usage
- π Lower data consumption
Type-safe error handling with sealed classes:
sealed class NetworkResult<out T> {
data class Success<T>(val data: T) : NetworkResult<T>()
sealed class Error : NetworkResult<Nothing>() {
data object NetworkError : Error()
data class ServerError(val code: Int) : Error()
data class UnknownError(val message: String?) : Error()
}
}User-friendly error messages:
- Network errors: "No internet connection. Please check your network."
- Server errors: Specific messages based on HTTP status codes
- Unknown errors: Graceful degradation
Using Hilt for dependency management:
@HiltViewModel
class PostViewModel @Inject constructor(
private val getPostsUseCase: GetPostsUseCase
) : ViewModel()All dependencies are provided through DI, making the code:
- Testable (easy to inject mocks)
- Maintainable (centralized dependency management)
- Scalable (easy to swap implementations)
The project uses Detekt with custom rules:
complexity:
LongMethod: threshold: 60
LargeClass: threshold: 600
CyclomaticComplexMethod: threshold: 15
style:
MaxLineLength: 120Run code quality checks:
./gradlew detektView HTML report:
app/build/reports/detekt/detekt.html
GitHub Actions workflow runs on every push and PR:
β Code quality check (Detekt) β Unit tests β Build debug APK β Build Android test APK β Upload test results
See .github/workflows/ci.yml for details.
- Add pagination for large lists
- Implement pull-to-refresh
- Add search functionality
- Implement multi-module architecture
- Add more comprehensive UI tests
- Integrate Firebase Analytics
- Add crash reporting (Firebase Crashlytics)
- Implement dark theme support
- Add accessibility features
- Baseline profiles for performance
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Kotlin coding conventions
- Run Detekt before committing:
./gradlew detekt - Ensure all tests pass:
./gradlew test - Add tests for new features
This project is licensed under the MIT License - see the LICENSE file for details.
Your Name
- GitHub: @yourusername
- LinkedIn: Your LinkedIn
- JSONPlaceholder - Free fake API for testing
- Android Developers - Official documentation
- Jetpack Compose - Modern UI toolkit
- Hilt - Dependency injection library
Built with β€οΈ using Kotlin and Jetpack Compose
If you found this project helpful, please β star the repository!