Use MediatorLiveData To Query And Merge Multiple Data Source Type Into Single LiveData (Kotlin)

April 13, 2018

Assuming I need to fetch a list of Password and Category, merging them into a single LiveData.

First, I create a Sealed Classes to represent both data type.

sealed class MergedData
data class PasswordData(val passwordItems: List<Password>): MergedData()
data class CategoryData(val categoryItems: List<Category>): MergedData()

Then I create a MediatorLiveData to fetch both data type.

fun fetchData(): MediatorLiveData<MergedData> {
    val liveDataMerger = MediatorLiveData<MergedData>()
    liveDataMerger.addSource(passwordDataSource.fetchAll(), {
        if (it != null) {
            liveDataMerger.value = PasswordData(it)
        }
    })
    liveDataMerger.addSource(categoryDataSource.fetchAll(), {
        if (it != null) {
            liveDataMerger.value = CategoryData(it)
        }
    })
    return liveDataMerger
}

Lastly I observe the LiveData and make sure both data sets are received before processing.

val liveData = fetchData()

var passwordItems: List<Password>? = null
var categoryItems: List<Category>? = null

liveData.observe(activity, object : Observer<MergedData> {
    override fun onChanged(it: MergedData?) {
        when (it) {
            is PasswordData -> passwordItems = it.passwordItems
            is CategoryData -> categoryItems = it.categoryItems
        }

        if (passwordItems != null && categoryItems != null) {
            // both data is ready, proceed to process them


            // stop observing
            liveData.removeObserver(this)
        }
    }
})  
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.