A sample Android application with a strong focus on a clean architecture, automated unit and UI testing and continuous integration.

Overview

CI codecov

Android playground

This is a sample Android application with a strong focus on a clean architecture, automated unit and UI testing and continuous integration.

The application shows a list of Marvel characters using the Marvel API with the option to search for characters, and a details page showing the selected character profile.

Building the project

In order to build this project, an API key needs to be provided in the local.properties file using the following scheme:

api.ts={YOUR_API_TS}
api.key={YOUR_API_KEY}
api.hash={YOUR_API_HASH}

More details for getting an API key can be found here.

Architecture

The application architecture is built based on Uncle Bob's Clean Architecture, and to enforce a proper separation of concerns and limiting boundaries, the project has been divided into 4 modules:

  • domain: It contains the entities, repositories interfaces and use cases (interactors) of the application. This module's dependencies are as small as possible, and should never depend on any networking or persistency library.

  • data: It contains the networking and persistency libraries as well as the repository implementations of the domain layer through dependency injection.

  • presentation: It contains the UI and view models of the application. The view models receive in their constructor the domain use cases for fetching or updating the data. Note this module does not add a dependency on the data module.

  • app: It's the top-most module, its only job is to bring together the other modules and provide the Android's Application and Activity classes.

Libraries

  • Coroutines for background work and observer pattern with Flow.

  • OkHttp and Retrofit for networking.

  • Kotlin Serialization for JSON parsing.

  • Hilt for dependency injection. This was preferred over other pure Kotlin libraries because Hilt/Dagger has support for javax @Inject annotations which alongside the Dagger KAPT processor can create our dependencies factories, saving us from writing this boilerplate code. This is especially useful for view models that need several use cases.

  • Room for database persistency.

  • View Model for writing our view models.

  • Jetpack Compose for building the UI.

  • Jetpack Compose Navigation for UI navigation.

  • Accompanist for system bars tinting and animated navigation.

  • Paging for paginated listings.

  • Kotest for writing the unit tests.

  • MockK for mocking dependencies on our tests.

  • Robolectric for running unit tests that require an Android context.

  • Jetpack Compose Test for UI testing.

  • JaCoCo for code coverage reports.

How it works

When the application is started, our Compose app will create a Navigation which pushes the CharacterListScreen on top of the navigation graph. The listing screen then calls the hiltViewModel () function on its constructor and Dagger/Hilt will create an instance of our view model with the dependencies we have declared on its primary constructor (it must be annotated with @Inject). If Dagger/Hilt can't create any of its dependencies, it will throw a compile time error rather than a runtime error due to its compile-time validation graph. The injection will happen recursively, this means we're going to have our repositories and data sources ready for work.

Now that CharacterListViewModel is instantiated, we can start requesting data to the GetCharactersPaginated use case by invoking it with a query parameter (null by default, which means list all characters) and this will return us an instance of a PagingSource to request data page by page. Every time a page is requested, it calls the method getCharacters of our CharacterRepository interface with the current page and query. Since Dagger has injected the dependency, we will actually be using the CharacterRepositoryImpl of our data module (to which the ViewModel does not have direct access thanks to the multi-module approach), and this repository will delegate the remote fetching to the CharacterRemoteDataSource that also delegates on a MarvelApi Retrofit instance (also injected) and this is where our request is actually made. When the data is available, it returns it to the CharacterRemoteDataSource where the response is mapped to an entity of our domain (called CharacterOverview) and our CharacterLocalDataSource saves the result on the Room database. Finally, the result is returned to the use case and then to the PagingSource.

Since we developed the UI using Jetpack Compose, we have a reactive UI that is updated automatically whenever there's a new update to the PagingSource thanks to the .collectAsLazyPagingItems() function. While this request was being processed, we had a loading state in the screen, but now that our first page has arrived, we can start rendering the first page on the screen.

We also account for any possible error (use cases MUST always handle any possible error thrown from the backend and return a custom Result class if needed), like a request failed due to network unavailable. In this case, an error page is shown, where we can retry our request. The UI will then go back to the loading state and finally the content state when available. Thanks to the Paging library, we will also request the following pages as the list is scrolled down.

The user is also presented a search icon in the toolbar in case he wants to query a specific character, and when he taps the enter button of the keyboard, the ViewModel restarts the PagingSource by calling again our use case with the provided query, then the CharacterListViewState is updated and the whole process starts over.

When a result of the list is tapped, Navigation handles our intent and pushes the CharacterDetailsScreen on top of the listing screen. Then, similar as before, a CharacterDetailsViewModel is instantiated with its declared the dependencies (a SavedStateHandle for retrieving the character id and the GetCharacter use case) and the screen renders a loading state while our data is retrieved. Our use case then calls the method getCharacter of our repository with the selected character id, and then the method getCharacterDetails on our CharacterRemoteDataSource which then makes the network request through our MarvelApi Retrofit instance. Once the data is ready, it's mapped to our entity CharacterDetails and returned to the repository, which also saves the data locally (as a plus, if this request fails, it tries to fetch the data locally, so if we have it cached, we return that data, otherwise the error is rethrown) and returns it to the use case, where we return a custom Result object handling every possible situation (either Success, NotFound or Error result). This result is finally returned to the ViewModel, which pushes a new CharacterDetailsViewState and forces a UI recomposition to reflect the new state.

Continuous Integration

The application automatically runs unit tests and UI tests on every commit thanks to Github CI and code coverage reports are pushed to CodeCov.

You might also like...
A sample project which can be used as a base in order to develop Media Library applications for Android TV.  Follow the series of blogs starting at http://www.malmstein.com/blog/2014/10/21/building-applications-for-android-tv/ in order to keep up to date with the process How to apply meaningful and delightful motion in a sample Android app
How to apply meaningful and delightful motion in a sample Android app

Applying meaningful motion on Android How to apply meaningful and delightful motion in a sample Android app Read the complete post at https://medium.c

A sample Android app that demonstrates how to use Firebase Authentication, Crashlytics, Cloud Firestore and Hilt with Jetpack Compose UI

showcase.mp4 Make it So This is a sample Android app that demonstrates how to use Firebase Authentication, Crashlytics, Cloud Firestore and Hilt with

A sample Android app which showcases advanced usage of Dagger among other open source libraries.
A sample Android app which showcases advanced usage of Dagger among other open source libraries.

U+2020 A sample Android app which showcases advanced usage of Dagger among other open source libraries. Watch the corresponding talk or view the slide

Sample material transition animations for Android
Sample material transition animations for Android

See ListOfThings for a newer implementation. Android Material Transitions This Android project samples some Material Design-ish transitions for list i

Sample Project for Android Support Library 23.2
Sample Project for Android Support Library 23.2

SnapShot: Contains features Vector Drawable Animated Vector Drawable AppCompat DayNight theme Bottom Sheets Using BottomSheetDialog in day-night mode.

This project is focused on the sample using the API's new preview version of Android-L, use of transitions, shadows etc...

Android L preview example Description This project is focused on the sample using the API's new preview version of Android-L, use of transitions, shad

PlayPauseDrawable 1.9 0.0 L5 Java This is a sample Play & Pause Drawable with morphing animation for Android
PlayPauseDrawable 1.9 0.0 L5 Java This is a sample Play & Pause Drawable with morphing animation for Android

#PlayPauseDrawable #Deprecated please go to https://github.com/tarek360/Material-Animation-Samples This is a sample Play & Pause Drawable with morphin

This project is focused on the sample using the API's new preview version of Android-L, use of transitions, shadows etc...

Android L preview example Description This project is focused on the sample using the API's new preview version of Android-L, use of transitions, shad

Owner
null
PokeCard Compose is a demo app 100% write in Compose, Flow and Koin based on MVI Clean Architecture 🐱⚡️

A Pokemon Card demo app using Jetpack Compose and Koin based on MVI architecture. Fetching data from the network with Ktor and integrating persisted data in Room database with usecase/repository pattern.

Lopez Mikhael 104 Nov 27, 2022
Clean Architecture Crypto App

Hi, this is the first project I did with CleanArchitectureMvvm and it is basic and not too complicated. I hope it will be useful for other friends as well.

Soran Mahmoodi 0 Oct 28, 2021
📚 Sample Android Components Architecture on a modular word focused on the scalability, testability and maintainability written in Kotlin, following best practices using Jetpack.

Android Components Architecture in a Modular Word Android Components Architecture in a Modular Word is a sample project that presents modern, 2020 app

Madalin Valceleanu 2.3k Dec 30, 2022
Android app for testing out various networking capabilities

Networking Tools Collection of handy networking tools for everyday development. Port Scanning Subnet Device Finder (discovers devices on local network

Akshat Tiwari 3 Dec 4, 2021
A sample app showing how to build an app using the MVI architecture pattern.

MVI Example This application was streamed live on Twitch to demonstrate how to build an application using MVI. You can find the VOD here for now: http

Adam McNeilly 46 Jan 2, 2023
Restaurant is a demo application based on modern Android application tech-stacks and MVVM architecture

Restaurant is a demo application based on modern Android application tech-stacks and MVVM architecture. Fetching data from the network via repository pattern.

Eslam kamel 25 Nov 20, 2022
Sample application demonstrating Android design and animation

android-movies-demo This is a sample application showing off some interesting design/development interactions for a talk given at Droidcon 2013. As it

Daniel Lew 359 Jan 1, 2023
Demo Android application using Gradle. Project is written entirely in Kotlin with MVVM architecture

Demo Android application using Gradle. Project is written entirely in Kotlin with MVVM architecture, Dagger / Hilt Dependency Injection, Room Database and Retrofit API Calls

Dejan Radmanovic 1 Apr 6, 2022
Quality-Tools-for-Android 7.5 0.0 L5 Java This is an Android sample app + tests that will be used to work on various project to increase the quality of the Android platform.

Quality Tools for Android This is an Android sample app + tests that will be used to work on various project to increase the quality of the Android pl

Stéphane Nicolas 1.3k Dec 27, 2022
Android sample app following best practices: Kotlin, Compose, Coroutines and Flow, Hilt, JetPack Navigation, ViewModel, MVVM and MVI, Retrofit, Coil

Foodies - Modern Android Architecture Foodies is a sample project that presents a modern 2021 approach to Android app development. The project tries t

null 362 Jan 2, 2023