A simple Android application that consumes the REST Countries API and demonstrates clean architecture, offline persistence, and modern Android development practices.
This project was implemented as part of an Android interview assignment under a strict 3-hour time limit.
- Displays a scrollable list of countries
- Shows:
- Country flag
- Country name
- Displays detailed country information:
- Flag
- Name
- Capital
- Currencies
- Local search by country name
- Filtering is performed on the already loaded dataset
- Debounced and distinct query handling
- Country data is fetched once from the API
- Persisted locally using Room
- UI always observes local database updates via Flow
- UI strings are externalized and separated
- A dedicated module exists for content and string resources
- The project is structured to support localization without architectural changes
The REST Countries API (v3.1) does not provide a locale-based query mechanism (for example ?lang=es).
Although country name translations are available in the API response (nativeName, translation maps), integrating full localization requires additional mapping and fallback logic.
Due to the strict 3-hour time constraint, full country name localization was intentionally not implemented.
However:
- A dedicated
contentmodule was created to host string resources - UI text is fully decoupled from business logic
- Localization can be added later without refactoring existing layers
This demonstrates awareness of internationalization concerns while keeping the implementation focused on the assignment’s core requirements.
The application follows Clean Architecture + MVVM, with clear separation of concerns:
-
data
- Retrofit API
- Room database
- Repository implementations
-
domain
- Use cases
- Repository interfaces
- Business logic
-
ui
- ViewModels
- Compose screens
- UI state
-
core
- Shared utilities (dispatchers, base components)
-
content
- String resources
- Localization-ready module
| Module | Responsibility |
|---|---|
core |
Shared utilities and base architectural components |
domain |
Business logic, use cases, repository contracts |
data |
API, Room database, repository implementations |
ui |
Screens, ViewModels, UI state |
content |
Strings and localization-ready resources |
In a production-scale application, the preferred approach would be to introduce fully separated feature-based modules such as:
countries-listcountry-detailssearch
Due to the limited scope and time constraints of this assignment, the implementation focuses on demonstrating clean architecture fundamentals rather than additional modular complexity.
The current setup still ensures:
- Clear layer separation
- High maintainability
- Easy future extensibility
Unit tests were written for the most important layers.
-
CountriesListViewModelTest- Query updates
- Retry logic
- Refresh triggering
- Debounce and distinct filtering behavior
-
CountryDetailsViewModelTest- Loading state handling
- Null safety
- Error handling
- Restart logic
ObserveCountriesUseCaseTestObserveCountryDetailsUseCaseTest
Use cases are tested to verify correct delegation to the repository layer.
- Kotlin
- Coroutines + Flow
- Jetpack Compose
- Jetpack ViewModel
- Room Database
- Retrofit + Moshi
- Hilt Dependency Injection
- Turbine + MockK for testing
- Modular Clean Architecture
Given more time, the following enhancements could be added seamlessly:
- Localized country names based on device locale
- Feature-based UI modules
- Improved offline strategy (cache invalidation, background refresh)
- Enhanced UI animations and transitions
- Better empty and error state visuals
The current architecture supports all of the above without requiring refactoring.
- Flag images are not persisted manually
- Flags are displayed using the provided image URL
- Image caching is handled by the image loading library
Developed by Hovsep Arakelyan
Senior Android Developer