Introduction: Sample app using Kotlin, Coroutines, Architecture Components and more. With Unit and Instrumentation tests.
More: Author   ReportBugs   OfficialWebsite   

Sample Android App to access Discogs API.

This app performs basic REST call to obtain a public list of records from Discogs API, with the idea to test and showcase some Android architecture and coding patterns.

Code Features

  • Kotlin.
  • Coroutines.
  • Dependency injection with Koin.
  • Retrofit + Moshi.
  • Architecture Components.
  • Modularization.
  • Unit Testing.
  • Instrumentation Testing with Espresso.

App Modules

- app                  (App and MainActivity; Android)
- api                  (Retrofit Service; Kotlin)
- common-domain        (Kotlin)
- collection           
  | - collection-ui    (Fragment and ViewModel; Android)
  | - collection-data  (Use case; Kotlin)


Cool Examples

Dependency Injection with Koin

startKoin(this, listOf(

private val viewModel: CollectionViewModel by viewModel()

Retrofit with Coroutines

fun getCollectionItemsByFolder(
    @Path("username") username: String,
    @Path("folder_id") folderId: String,
    @Query("page") page: Int,
    @Query("per_page") perPage: Int
) : Deferred<Response<CollectionItemsByFolderResponse>>

Use Case Implementation with Coroutines and Arrow

private suspend fun requestItems(
    folder: String,
    page: Int
): Response<CollectionItemsByFolderResponse> {
    return discogsService.getCollectionItemsByFolder(
        username = "mike513",
        folderId = folder,
        page = page,
        perPage = PAGE_SIZE

Use Case Unit Test using Mockk and Coroutines

every {
        username = "mike513",
        folderId = "0",
        page = 1,
        perPage = 20
} returns CompletableDeferred(

ViewModel and LiveData with Coroutines (Kotlin 1.3)

loadingJob = launch(dispatcher) {
    val result = collectionUseCase.getCollectionPage("0", page)
    when (result) {
        is Either.Left -> Log.e("CollectionViewModel", result.a)
        is Either.Right -> {
            pages[page] =
            nextPage = result.b.nextPage

ViewModel Unit Test

val viewModel = CollectionViewModel(
    collectionUseCase = useCase,
    dispatcher = Dispatchers.Unconfined

val data = viewModel.liveData.value!!
assertEquals(1, data.size)

val item = data[0] as CollectionItem.AlbumItem
assertEquals(album, item.album)

Fragment Instrumentation Test with Espresso

fun load_single_item_page() {

    // Mock the use case to return a single item
    val collectionUseCase = mockUseCaseForSingleItem()

    // Configure dependency injection to provide ViewModel with Use Case

    // Launch Fragment in a Test Activity

    // Assert Album title is displayed in the list


Android Architecute Sample  Copyright (C) 2018  Miguel Beltran Febrer
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
Support Me
About Me
Google+: Trinea trinea
GitHub: Trinea