Skip to content

Blueprint Samples

These samples showcase how you may integrate Blueprint in your project by implementing a simple note taking app.

There are 2 flavors of the demo app:

  • demo-coroutines - powered by Kotlin Coroutines and Flow and various Blueprint libraries.
  • demo-rx - powered by RxJava 3 and various Blueprint libraries.

Dependencies

Since the 2 demo apps have identical functionality, we are able to share a lot of common code between the apps by having a couple of common library modules.

demo-coroutines

This app module uses the following Blueprint libraries:

It also depends on the demo-common and demo-testing-common modules.

demo-rx

This app module uses the following Blueprint libraries:

It also depends on the demo-common and demo-testing-common modules.

demo-common

This library module includes common code shared between the 2 apps such as resources, layouts, and in-memory cache.

demo-testing-common

This library module includes common UI testing infra code shared between the 2 apps such as instrumentation robots and test data.

Comparison

The demo apps follow Clean Architecture, but the only part relevant to Blueprint is the domain layer which contains Use Cases (also known as Interactors).

One of the key differences between the Coroutines-based and RxJava-based implementations is how Interactors are implemented:

  • The Coroutines-based implementation uses SuspendingInteractor for single-shot tasks and FlowInteractor for cold streams.
  • The RxJava-based implementation uses SingleInteractor and CompletableInteractor for single-shot tasks and ObservableInteractor for cold streams.
Single-shot Task Cold Stream
blueprint-interactor-coroutines SuspendingInteractor FlowInteractor
blueprint-interactor-rx3 SingleInteractor, CompletableInteractor ObservableInteractor

Consequently the 2 different Interactor implementations expose different async primitives to downstream:

  • Coroutines-based Interactors - expose suspend function and Kotlin Flow to consumers.
  • RxJava-based Interactors - expose RxJava Single, Completable and Observable to consumers.

Another difference is the wrapper APIs for encapsulated threading behavior:

  • The Coroutines-based implementation uses CoroutineDispatcherProvider from the blueprint-async-coroutines library.
  • The RxJava-based implementation uses SchedulerProvider from the blueprint-async-rx3 library.

They offer the same abstraction to help with DI and testing, but one interacts with Kotlin’s CoroutineDispatcher API and the other one interacts with RxJava’s Scheduler API.

Notes

While these samples implement layered-architecture and have comprehensive unit tests and UI tests, they most definitely do not represent how one should approach building a production quality app.

A number of important things are left out as our focus here is how the Blueprint libraries can be integrated in your codebase:

  • We implemented a very simple Dependency Injection (Service Locator to be precise) framework. Consider using Dagger or Koin in a real project.
  • Different layers (e.g. domain, data, presentation) should probably live in their own modules in a real project.
  • Both samples use AndroidX ViewModel in the presentation layer. For better managing complex states you might want to consider using a redux-based architecture that employs Uni-directional Data Flow. I personally recommend RxRedux and its Coroutines-based equivalent.
  • In a real project you will want to set up product flavors for different environments (e.g. mock, staging, production).
  • Obviously the apps don’t talk to any backend APIs and lack persistent storage.

For a better representation of a highly-modularized, production-quality app that uses Blueprint, you may want to take a look at ReleaseProbe.