Photos is a sample project by showing photos on the Android system.
This project takes advantage of best practices, many popular libraries and tools in the Android ecosystem. Most of the libraries are in the stable version unless there is a good reason to use non-stable dependency.
- Tech-stack
- 100% Kotlin + Coroutines - perform background operations
- Retrofit - networking
- Jetpack
- Navigation - in-app navigation
- LiveData - notify views about database change
- Lifecycle - perform an action when lifecycle state changes
- ViewModel - store and manage UI-related data in a lifecycle conscious way
- Room - store offline cache
- Dagger - dependency injection
- Coil - image loading library
- Modern Architecture
- Clean Architecture (at feature module level)
- Single activity architecture using Navigation component
- MVVM + MVI (presentation layer)
- Dynamic feature modules
- Android Architecture components (ViewModel, LiveData, Navigation)
- Android KTX - Jetpack Kotlin extensions
- CI
- GitHub Actions
- Automatic PR verification including tests, linters and 3rd online tools
- Testing
- Unit Tests (JUnit 5 via android-junit5)
- UT Tests (Espresso)
- Mockk - mocking framework
- UI
- Material design
- Reactive UI
- Static analysis tools
- Gradle
- Plugins (SafeArgs, android-junit5)
Feature related code is placed inside one of the feature modules. We can think about each feature as the reusable component, equivalent of microservice or private library.
This diagram presents dependencies between project modules (Gradle sub-projects).
Note that due usage of Android dynamic-feature
module dependencies are reversed (feature modules are depending on app
module, not another way around).
We have two kinds of modules in the application:
app
module - this is the main module. It contains code that wires multiple modules together (dependency injection setup,NavHostActivity
, etc.) and fundamental application configuration (retrofit configuration, required permissions setup, custom application class, etc.).- feature modules - the most common type of module containing all code related to a given feature.
Each feature module contains non-layer components and 3 layers with distinct set of responsibilities.
This layer is closest to what the user sees on the screen. The presentation
layer is a mix of MVVM
(Jetpack ViewModel
used to preserve data across activity restart) and
MVI
(actions
modify the common state
of the view and then new state is edited to a view via LiveData
to be rendered).
common state
(for each view) approach derives from Unidirectional Data Flow and Redux principles.
Components:
- View (Fragment) - presents data on the screen and pass user interactions to View Model. Views are hard to test, so they should be as simple as possible.
- ViewModel - dispatches (through
LiveData
) state changes to the view and deals with user interactions (these view models are not simply POJO classes). - ViewState - common state for a single view
- NavManager - singleton that facilitates handling all navigation events inside
NavHostActivity
(instead of separately, inside each view)
This is the core layer of the application. Notice that the domain
layer is independent of any other layers. This allows to make domain models and business logic independent from other layers.
In other words, changes in other layers will have no effect on domain
layer eg. changing database (data
layer) or screen UI (presentation
layer) ideally will not result in any code change withing domain
layer.
Components:
- UseCase - contains business logic
- DomainModel - defies the core structure of the data that will be used within the application. This is the source of truth for application data.
- Repository interface - required to keep the
domain
layer independent from thedata layer
(Dependency inversion).
Manages application data and exposes these data sources as repositories to the domain
layer. Typical responsibilities of this layer would be to retrieve data from the internet and optionally cache this data locally.
Components:
-
Repository is exposing data to the
domain
layer. Depending on application structure and quality of the external APIs repository can also merge, filter, and transform the data. The intention of these operations is to create high-quality data source for thedomain
layer, not to perform any business logic (domain
layeruse case
responsibility). -
RetrofitService - defines a set of API endpoints.
-
DataModel - defines the structure of the data retrieved from the network and contains annotations, so Retrofit (Moshi) understands how to parse this network data (XML, JSON, Binary...) this data into objects.
Below diagram presents application data flow when a user interacts with album screen
:
CI is utilizing GitHub Actions. Complete GitHub Actions config is located in the .github/workflows folder.
Series of workflows runs (in parallel) for every opened PR and after merging PR to main
branch:
./gradlew lintDebug
- runs Android lint./gradlew detekt
- runs detekt./gradlew ktlintCheck
- runs ktlint./gradlew testDebugUnitTest
- run unit tests./gradlew connectedCheck
- run UI tests./gradlew :app:bundleDebug
- create app bundle
- Add a list of favorite photos
- UI tests
- Create a core module
All - 54 hours
(4 hours) Research
(4 hours) Setting up project
(4 hours) Create Navigation, Architecture
(12 hours) Main screen. Album
(1 hour) Main screen. Button Add
(1 hour) Main screen. Button Reload All
(2 hours) Detail screen
(2 hours) Skeleton for Photos
(2 hours) Skeleton for Photos
(2 hours) Light/dark theme support
(8 hours) Write tests
(8 hours) Setting up code analyzers and CI/CD
(4 hours) Making a README.md file
There are a few ways to open this project.
Android Studio
->File
->New
->From Version control
->Git
- Enter
https://github.com/igorwojda/android-showcase.git
into URL field an pressClone
button
- Run
git clone https://github.com/igorwojda/android-showcase.git
command to clone project - Open
Android Studio
and selectFile | Open...
from the menu. Select cloned directory and pressOpen
button
In folder 'apk' you can find apk's application
This is project is a sample, to inspire you and should handle most of the common cases, but please take a look at additional resources.
- Kotlin Coroutines - Use Cases on Android - most popular coroutine usages
Other high-quality projects will help you to find solutions that work for your project:
- Android-showcase - Project that presents a modern approach to Android application development
- Theatre - Project using Clean Architecture + MVVM + Reactive Extensions + Android Architecture Components
- Android sunflower complete
Jetpack
sample covering all libraries - Plaid - a showcase of Android material design
- Clean Architecture boilerplate - contains nice diagrams of Clean Architecture layers
- Android samples - official Android samples repository
[![Nor35(https://github.com/Nor35)]