A simple android application that consumes data from https://dummyapi.io/ with a clean architecture, fully compatible with Android 11, supporting light and dark theme (see screenshots) and completely written in Kotlin.
- App Walk-through
- App Installation
- API key
- Building source
- Top Features
- Architecture
- Testing
- Libraries
- Extras
The first screen in the app gives the user the option of selecting whether the data will be loaded from the real https://dummyapi.io/ API or a mocked server version. Sometimes https://dummyapi.io/ may be down.
You can download the APK from releases.
The app consumes API from https://dummyapi.io/. Get an api key here
- In the
local.properties
file in your project-level directory, add the following code to the file. ReplaceYOUR_APP_KEY
with your Dummy API app ID.
dummy.api.app.id=YOUR_API_KEY
To build this project, you require:
- Android Studio 4.1.0 or higher
- Gradle 6.5 or higher
- Multi-module clean architecture
- Kotlin coroutines with Flow
- Dependency injection with Dagger-Hilt
- View abstracted from Fragment like componentizationArch
- API request with Retrofit and Moshi for JSON serialisation and deserialization
- Local persistence with Room
- Paging with Paging 3.0
- CI with Github actions
- Code coverage with jacoco with reports uploaded to codecov
- Code lint check with Ktlint using a gradle plugin
- Static code analysis with detekt
- Dependency management with buildSrc (Kotlin DSL)
- Dependency updates with buildSrcVersions
- Git hooks to perform ktlint, detekt and lint checks before committing
The application follows the clean architecture concept. As software architecture involves the design decisions that are hard to change, we should take an approach that does not result in coupling of the various components of the software. This makes it easy to make changes as it scales. The presentation layer for each feature uses a minimalistic version of the MVI architecture. With this in mind, the project is organised into modules as follows:
This module contains features supported by the application. At present, only the users
feature is implemented. Other features can be added as modules as the project scales.
The users feature has two screens. One that shows a list of users, the other for displaying user details. The module defines both the view and presentation for the feature. The presentation is implemented using ViewModel + Fragment combination with a minimalist MVI architecture
Most MVI architecture implementations use Fragment/Activity as views. In my opinion, these components are best suited as view controllers.
In the project, the view is abstracted away from the Fragments into UIViews, which can be thought of as view components. The Fragments observe events from the ViewModel and delegates respective states to the view.
The core module just sets up the implementation of the data
layer of the application. It provides the remote
and cache
layers. Concurrency in the application is implemented using Kotlin coroutines (+ Flow) and this module provides the implementation for the dispatchers used in the application.
This module contains utility classes, extension functions, custom views shared by the android related modules. Most of the android modules depend on this module. Having the common classes here prevents duplication of code.
This module contains classes shared in unit tests in all modules.
This module connects all other modules. Provides navigation implementation with the Navigation Architecture Component library.
Testing is done with Junit4 testing framework, and with Google Truth for making assertions. Mockk is used to provide mocks in some of the tests. The tests run on the CI and the code coverage report is generated by jacoco can be tracked here.
- Material Components
- Constraint Layout
- Retrofit for REST api communication
- Moshi for JSON serialisation and deserialization
- Mockk for mocking in tests
- Dagger-Hilt for dependency injection
- Kotlin Flow for concurrency
- Turbine for testing flow
- ViewModel & LiveData
- Navigation Architecture Component
- Room for database
- Glide for image loading
- ViewBinding
- Paging 3.0
- Kotlin Delegates
- Ktlint gradle plugin for code lint checks
- Detekt for static code analysis
- LeakCanary for detecting memory leaks in development
The gradle script uses Kotlin Gradle DSL (buildSrc ) which brings Kotlin's rich language features to gradle configuration. The project also uses detekt to detect code smells and ktlint to enforce proper code style. Github actions handles continuous integration, and runs detekt, ktlint, lint and unit tests concurrently. A pre-commit git hook verifies the project's code style before committing code. Test coverage reports are uploaded to codecov.
Other things to do
- Improve presentation layer (try out ReduxComponents)
- Write UI tests
- Improve Unit test coverage
- Improve UI/UX