Android Architecture starring Kotlin Coroutines, Jetpack (MVVM, Room, Paging), Retrofit and Dagger 2

Over years Android architecture evolved to support complex, robust, production-quality apps on any scale. It is great to see how Google recommendations are aligned with Android community needs and choices. In the last years Google has promoted Kotlin as first class citizen, introduced Guide to app architecture starring uncle’s Bob Clean Architecture concept with MVVM presentation pattern. We have been given out of box architecture puzzles packed into Architecture Components and Android Jetpack. Retrofit, RxJava and Dagger have been taken into official tutorials.
Last, but not least Kotlin Coroutines have been landed at Google IO 2019. The inspiration comes from Reactive Programming (frameworks like RxJava). Kotlin Coroutines manage background threads with simplified code and reducing needs for callbacks.
Yet when it comes to combine all architecture puzzles together into simple client application it is difficult to find open sourced app sample to follow. One of the Infinity Stone always missing.

We are going to implement sample app starring Google Guide to app architecture (based on MVVM and Repository patterns), using Android Jetpack(ViewModel, LiveData, Room, Paging, Navigation), Retrofit and Dagger 2. App is entirely written in Kotlin. Special guest is Kotlin Coroutines which we will use instead of RxJava2 for basic use case of data loading.
We will implement app step by step mastering architecture concepts. Note: The goal of article is to give overview of Android Architecture current state combining all of components together into simple production-quality application. The article assumes familiarity of reader with concepts and library mentioned.
Lets dive into it!
The full source code of this project together with full list of libraries used can be found on GitHub:
The project we will develop
Every Android Engineer had or will have a need to write basic application from scratch. Either for new project, prototyping or interviewing. The classic application consists of 2 screens: infinity scrolling list of items and details view using network and persistency.
I am big fan of LEGO® mini figures and LEGO® in general, therefore I have chosen to write a simple catalog to browse sets. The app consists of 3 screens: list of themes, infinity list of sets and set details.

Architecture overview
Clean architecture assumes separation of concerns with UI(Activity, Fragment, View), Presentation(ViewModel) and Data(Repository) layers. ViewModel helps to handle user interaction, save current state of app and automatically manage Android UI components lifecycle via LiveData.
Repository serves as data point, where ViewModel knows nothing about source of data. It is up to repository to decide whether local or remote data should be given back to user. It serves well to handle data synchronisation conflicts.

Lets show list of LEGO® themes to user
Lets develop an application screen with list of themes. We will load a list of themes and show them to user. We will support offline mode and fetch data from REST API.
Model
User Interface and Experience
Lets start from writing a layout for fragment in fragment_themes.xml
. Data binding
is used to bind data to view in declarative style. View Binding
as a part of Data Binding is used to have references of views in a fragment.
Then lets add list_item_theme.xml
with item UI representation.
In order to display items in list and reuse view resources lets write LegoThemeAdapter
.
Lets write a LegoThemeFragment
with viewModel
injected.
A Fragment
starts observe a LiveData<Result<List<LegoTheme>>> themes
from viewModel
. Thats where magic begins. LiveData
is lifecycle aware and observing data for any new changes.
Error and Loading states handling
Note that Fragment
observes a LiveData
of a Result
object. It intends to provide feedback to UI, whether it should show Success
, Loading
or Error
state. In case of Success
we show loaded data, Loading
will trigger progressBar
appearance and Error
will give feedback to user via Snackbar
.
Dependency injection with Dagger 2
Dependency Injection
and Dagger 2
is comprehensive topic to discuss in one article with architecture overview. But one case deserves an attention: injection of viewModel
.
Since Fragment
is initialised by Android SDK
, we can not inject viewModel on construction phase. Therefore we will inject it via ViewModelFactory
.
The full implementation of app dependancy graph can be found on Github.
Presentation with MVVM, LiveData and Lifecycles
Thankfully to ViewModel
and LiveData
lifecycle awareness our LegoThemeViewModel
is very simple. It has only LegoThemeRepository
as a dependency in order to provide data.
Repository with Kotlin Coroutines based on single source of truth strategy
In order to avoid synchronisation discrepancies it is required to define a single source of truth. The Repository
serves as an abstract source of data for Presentation Layer (viewModel
). Although Repository
should decide which data source is truth. Lets define a local database
as a source of truth. Whenever data is requested we will give back local copy, then we fetch remote data, save it to database
, which will automatically notify Repository
about new data available.
Lets look at data flow:

Here LiveData
and Coroutines
come to rescue and simplify code. Lets look at LegoThemeRepository
.
We have got 2 dependencies: dao: LegoThemeDao
and remoteSource: LegoThemeRemoteSource
. Themes are received via Coroutines suspend functions
in order to make this calls asynchronous and unblock main UI thread
from work. Lets dive into our SingleSourceOfTruth.kt
implementation in order to understand multithreading mechanism under the hood.
We are using extension function liveData()
from CoroutineLiveData.kt
class of LiveData
library. liveData()
function accepts Coroutine Dispatcher
in order to choose running tread.
There are 4 types of Dispatchers
:
- Default (Designed for heavy computational work)
- Main (Main thread operating with UI objects)
- IO (Designed for offloading blocking IO tasks like network, database operations)
- Unconfined (Not confined to any specific thread)
In our case Dispatchers.IO
is exactly what we need. We use Coroutines suspend functions
in order to fetch, load and save data. To communicate to UI with Success
, Loading
or Error
state we use emit()
function, which automatically notify observer on Main UI thread.
Persistency with Room and Kotlin Coroutines

Room database
has built in support of LiveData
and Kotlin Coroutines
, which make multithreading easy task. Lets have a closer look at LegoTheme Entity
and LegoThemeDao
.
Network with Retrofit and Kotlin Coroutines
Retrofit
has a built in support for Kotlin Coroutines functions
too. For this just define your API end point methods with suspend
keyword. Fetched data will be saved into database, it will trigger database to notify viewModel
with liveData
of updated information. Therefore we do not need to return liveData
from Retrofit
call directly.
In order to handle errors lets write BaseDataSource
class, which takes Retrofit Response
object and transform it either to Success
or Error
. This state will be communicated to UI eventually via Repository -> ViewModel -> Fragment
.
Paging library
Since we accomplished screen with limited amount of Themes we can tackle screen with Sets, where we need to show infinity number of items. We want to load and display small chunks of data at a time. For this purpose lets use Paging
library.
Good news that Room
database support offline paging. It works like a charm in combination with Paging
. A minimum amount of code need to written. All you need to do is to change your Dao class
method from LiveData<List<T>>
to DataSource.Factory<Int, T>
.
Then using LivePagedListBuilder
it can be converted to known LiveData
which will be observed in viewModel
.
For online Paging
PageKeyedDataSource
can be created, where API endpoints will be used in order to scroll pages forward and back.
Lets see LegoSetRepository
with functions to observe paged data lists locally and remote.
Pros: Paging is easy to use for offline and online sources separately.
Cons:
- Error handling is not straightforward, it requires to make custom error callbacks;
- Paging requires non trivial customisation in order to implement Single Source of Truth strategy loading pages from database and load more items on a fly from server. Therefore for simplicity of this case study, current app uses separate online and offline paging. Repository choses local or remote paging depending on user available connectivity.
CoroutineWorker with Work Manager
Work Manager
support Kotlin Coroutines
via CoroutineWorker
class. It does not provide async thread to run on by default like IntentService
. So we need to use coroutineScope
and withContext()
function specifying working thread via chosen Dispatcher
. Let look at SeedDatabaseWorker
example which preloads database items on database create event.
Navigation component
Navigation component structures navigation and show all transitions in one diagram via xml. It is great to see all transition in one place having control over them. Library eliminates boilerplate code for fragment state managing. Two additional perks are default animations of screen transactions, parameter definition in place with fragment declaration.
Navigation component serves greatly for purpose of basic application. Although from experience with more complex applications, which uses BottomNavigationView and other navigation patters, things become not trivial and require customisation. So keep in mind scale of your application when you decide to use Navigation component.
I think within time and our community impact component will evolve into comprehensive solution.
Lets have a closer look at nav_main.xml
.
Summary
That’s it! We have just completed an application using Kotlin Coroutines, Android Jetpack(ViewModel, LiveData, Room, Paging, Navigation), Retrofit and Dagger 2. Application is scalable and robust thankfully to designed Architecture based on Guide to app architecture.
We can see that Kotlin Coroutines in combination with Kotlin built in functions and LiveData support is a strong alternative to RxJava2. It eliminates callbacks and being less verbose, making code more concise. Also having less 3rd party dependencies is great benefit. Kotlin Coroutines serve great for basic application and have potential for big scale solutions.
I hope this Architecture Overview combined with all used components will boost your productivity and expertise!
I would like to see your opinion and experience with current Architecture and components below in comments.
In next article I would like to address Android Architecture decisions. How to not blindly follow newest trends, but pragmatically ponder pros and cons of every architecture decision we make. Stay tuned!
If you find this tutorial useful your Claps will be much appreciated and inspiring for the next articles!
The full source code of this project together with full list of libraries used can be found on GitHub: