igorwojda / android-showcase

πŸ’Ž Android application following best practices: Kotlin, Coroutines, JetPack, Clean Architecture, Feature Modules, Tests, MVVM, DI, Static Analysis...
MIT License
6.52k stars 895 forks source link
android android-application architecture best-practices clean-architecture gradle jetpack kotlin kotlin-coroutines mvvm

πŸ’Ž Android Showcase 2.0

Kotlin Version AGP Gradle

Codebeat Badge CodeFactor

The Android Showcase project exemplifies modern Android application development methodologies and provides comprehensive architectural guidance. By integrating popular development tools, libraries, linters, and Gradle plugins, along with robust testing frameworks and Continuous Integration (CI) setup, this project offers a holistic sample of a fully operational Android application.

The primary focus of this project lies in promoting a modular, scalable, maintainable, and testable architecture. It incorporates a leading-edge tech-stack and embodies the finest practices in software development. While the application may appear straightforward, it encompasses all the crucial components that lay the groundwork for a robust, large-scale application.

The design principles and architectural choices applied in this project are ideally suited for larger teams and extended application lifecycles. This application is not just about showcasing functionalities, but it is also a testament to how well-structured and well-written code serves as a stable backbone for scalable and maintainable software development projects.

Application Scope

The android-showcase is a simple application that presents information about various music albums. This data is dynamically sourced from the Last.fm music platform API.

The app has a few screens located in multiple feature modules:

Tech-Stack

This project takes advantage of best practices and 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.

Architecture

By dividing a problem into smaller and easier-to-solve sub-problems, we can reduce the complexity of designing and maintaining a large system. Each module is an independent build block serving a clear purpose. We can think about each feature as a reusable component, the equivalent of microservice or private library.

The modularized code-base approach provides a few benefits:

Module Types And Module Dependencies

This diagram presents dependencies between project modules (Gradle sub-projects).

module_dependencies

We have three kinds of modules in the application:

Feature Module Structure

Clean Architecture is implemented at the module level - each module contains its own set of Clean Architecture layers:

module_dependencies_layers

Notice that the app module and library_x modules structure differs a bit from the feature module structure.

Each feature module contains non-layer components and 3 layers with a distinct set of responsibilities.

feature_structure

Presentation Layer

This layer is closest to what the user sees on the screen.

The presentation layer mixes MVVM and MVI patterns:

The common state is a single source of truth for each view. This solution derives from Unidirectional Data Flow and Redux principles.

This approach facilitates the creation of consistent states. The state is collected via collectAsUiStateWithLifecycle method. Flows collection happens in a lifecycle-aware manner, so no resources are wasted.

Stated is annotated with Immutable annotation that is used by Jetpack compose to enable composition optimizations.

Components:

Domain Layer

This is the core layer of the application. Notice that the domain layer is independent of any other layers. This allows making domain models and business logic independent from other layers. In other words, changes in other layers will not affect the domain layer eg. changing the database (data layer) or screen UI (presentation layer) ideally will not result in any code change within the domain layer.

Components:

Data Layer

Encapsulates application data. Provides the data to the domain layer eg. retrieves data from the internet and cache the data in disk cache (when the device is offline).

Components:

This application has two Data Sources - Retrofit (used for network access) and Room (local storage used to access device persistent memory). These data sources can be treated as an implicit sub-layer. Each data source consists of multiple classes:

Both Retrofit API Data Models and Room Entities contain annotations, so the given framework understands how to parse the data into objects.

Data Flow

The below diagram presents application data flow when a user interacts with the album list screen:

app_data_flow

Dependency Management

Gradle versions catalog is used as a centralized dependency management third-party dependency coordinates (group, artifact, version) are shared across all modules (Gradle projects and subprojects).

All of the dependencies are stored in the settings.gradle.kts file (default location). Gradle versions catalog consists of a few major sections:

Each feature module depends on the feature_base module, so dependencies are shared without the need to add them explicitly in each feature module.

The project enables the TYPESAFE_PROJECT_ACCESSORS experimental Gradle feature to generate type-safe accessors to refer other projects.

// Before
implementation(project(":feature_album"))

// After
implementation(projects.featureAlbum)

Logcat debugging

To facilitate debuting project contains logs. You can filter logs to understand app flow. Keywords:

CI Pipeline

CI is utilizing GitHub Actions. The complete GitHub Actions config is located in the .github/workflows folder.

Pull Request Verification

Series of workflows run (in parallel) for every opened PR, and after merging PR to the main branch:

The following tasks cab be executed locally to make codebase compliant with the rules:

Design Decisions

Read related articles to have a better understanding of underlying design decisions and various trade-offs.

What This Project Does Not Cover?

The interface of the app utilizes some of the modern material design components, however, is deliberately kept simple to focus on application architecture and project config.

Getting Started

There are a few ways to open this project.

Android Studio

  1. Android Studio -> File -> New -> From Version control -> Git
  2. Enter https://github.com/igorwojda/android-showcase.git into URL field and press Clone button

Command-line And Android Studio

  1. Run git clone https://github.com/igorwojda/android-showcase.git command to clone the project
  2. Open Android Studio and select File | Open... from the menu. Select the cloned directory and press Open button

Plugins

It is recommended to install Detekt to Android Studio. To configure the plugin open Android Studio preferences, open Tools, open Detekt and add detekt.yml configuration file.

Upcoming Improvements

This project is under active development and it is being occasionally refined.

Check the list of all upcoming enhancements.

Inspiration

Here are a few additional resources.

Cheatsheet

Android Projects

Other high-quality projects will help you to find solutions that work for your project (random order):

Other

Known Issues

Contribute

This project is being maintained to stay up to date with leading industry standards. Please check the CONTRIBUTING page if you want to help.

Author

Follow me

Follow me

License

MIT License

Copyright (c) 2019 Igor Wojda

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Animations License

Flowing animations are distributed under Creative Commons License 2.0: