This is a portfolio project that demonstrates the use of Compose, Material 3, Coroutines including Flows, Hilt, Jetpack Navigation, ViewModel, MVI and Clean Architecture.
A catalogue of cat breeds with detailed information about each breed and photos
Home Screen | Detail Info | Detail Images |
---|---|---|
Home Screen | Detail Info | Detail Images |
---|---|---|
Home Screen | Detail Info Top | Detail Info Bottom | Detail Images |
---|---|---|---|
Home Screen |
---|
The app is built in MVI, where each UI 'screen' has its own ViewModel, which exposes a single StateFlow containing the entire view state. Each ViewModel is responsible for subscribing to any data streams and objects required for the view, as well as exposing functions which allow the UI to send events.
Using the HomeScreen as an example within the com.tinnovakovic.catcataloguer.presentation.home
package:
- The ViewModel is implemented as
HomeViewModel
, which exposes a MutableStateFlow for the UI to observe. HomeContract
contains the complete view state for the home screen as an @Immutable data classUiState()
. It also exposes the functions which enable the UI to send events to the ViewModel in the form of a sealed classsealed class UiEvents : BaseUiEvent
.- The Compose
HomeScreen
uses HomeViewModel, and observes it's UiState as Compose State, usingcollectAsStateWithLifecycle()
:
val viewModel = hiltViewModel<HomeViewModel>()
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
This MVI pattern is made scalable by inheriting the base classes in com.tinnovakovic.catcataloguer.shared.mvi
, BaseUiEvent
, BaseUiState
and BaseViewModel
The app uses Clean Architecture.
- The Data layer integrates Networking sources from Retrofit and Persistent sources from Room using the Repository pattern and merges them together using the Paging 3 library to fetch paginated data from the API and Room, furthermore it exposes UI models mapped from the Network and Persistent models which are incapsulated within the Data layer.
- The Domain layer manages business logic using the UseCase pattern.
- The Presentation layer uses the MVI pattern as described above.
To solve pagination the Paging 3 library was used, this handling paginating the API data and paginating the persisted data as well, this ensures that the application only fetches a manageble amount of data at once and that data is still available when offline.
DataStore is used to saved the users prefered sort_order for the main screen, they can choose between sorting by the cat breed name and the origin.
To ensure the app is accessibile to all users I've put focus on ensuring the app looks and functions well when the font and the screen zoom is at the largest system settings, I encourage you to try it.
- Kotlin
- Dagger Hilt
- Coroutines
- Compose
- Architecture
- Clean Architecture
- MVI
- Jetpack Navigation
- Testing
- JUnit5
- Mockk
You need to get your own APIKEY from here https://thecatapi.com/ and insert it into your local.properties file:
THE_CAT_API_KEY = {API_KEY}