KunBa
KunBa

Reputation: 255

How to simply add another source to MediatorLiveData in kotlin?

I want to combine multiple data sources in a MediatorLiveData. Unfortunately, there are not many examples yet. So in my ViewModel I have

//all lists have been declared before

val playerList = MediatorLiveData<List<Player>>()

init {
    playerList.addSource(footballPlayerList) { value ->
        playerList.value = value
    }
    playerList.addSource(basketballPlayerList) { value ->
        playerList.value = value
    }
}

But apparently this will always override the current value of playerList. I mean I could build some hacky workarounds with helper variables like _playerList but maybe there is an easier solution?

Upvotes: 3

Views: 5905

Answers (2)

Ahmet B.
Ahmet B.

Reputation: 1674

Here is a simple example

class MergeMultipleLiveData : ViewModel() {

private val fictionMenu: MutableLiveData<Resource<RssMenu>> = MutableLiveData()
private val nonFictionMenu: MutableLiveData<Resource<RssMenu>> = MutableLiveData()
val allCategoryMenus: MediatorLiveData<Resource<RssMenu>> = MediatorLiveData()

init {
    getFictionMenus()
    getNonFictionMenus()
    getAllCategoryMenus()
}

private fun getAllCategoryMenus() = viewModelScope.launch(Dispatchers.IO) {
    allCategoryMenus.addSource(fictionMenu) { value ->
        allCategoryMenus.value = value
    }
    allCategoryMenus.addSource(nonFictionMenu) { value ->
        allCategoryMenus.value = value
    }
}

private fun getFictionMenus() = viewModelScope.launch(Dispatchers.IO) {
    fictionMenu.postValue( // todo )
}

private fun getNonFictionMenus() = viewModelScope.launch(Dispatchers.IO) {
    nonFictionMenu.postValue( // todo )
}

}

And in your fragment you can observer as;

viewModel.allCategoryMenus.observe(viewLifecycleOwner) {
        // todo
    }

Upvotes: 0

KunBa
KunBa

Reputation: 255

Having done quite some research.. I found it out. Here is an example

fun blogpostBoilerplateExample(newUser: String): LiveData<UserDataResult> {

val liveData1 = userOnlineDataSource.getOnlineTime(newUser)
val liveData2 = userCheckinsDataSource.getCheckins(newUser)

val result = MediatorLiveData<UserDataResult>()

result.addSource(liveData1) { value ->
    result.value = combineLatestData(liveData1, liveData2)
}
result.addSource(liveData2) { value ->
    result.value = combineLatestData(liveData1, liveData2)
}
return result
}

The actual combination of data is done in a separate combineLatestData method like so

private fun combineLatestData(
    onlineTimeResult: LiveData<Long>,
    checkinsResult: LiveData<CheckinsResult>
): UserDataResult {

val onlineTime = onlineTimeResult.value
val checkins = checkinsResult.value

// Don't send a success until we have both results
if (onlineTime == null || checkins == null) {
    return UserDataLoading()
}

// TODO: Check for errors and return UserDataError if any.

return UserDataSuccess(timeOnline = onlineTime, checkins = checkins)
}

Upvotes: 3

Related Questions