Search code examples
android-architecture-componentsandroid-livedataandroid-viewmodelkotlin-coroutinesmutablelivedata

How to change particular property value of a class in a LiveData<List<T>> (in my case LiveData<List<Item>>) using MediatorLiveData


The Item.kt class is

@Entity(tableName = "item")
class Item(
    val id: Long,
    val title: String,
    ) {
    @Ignore
    var selection: Boolean = false
}

Then i make a query to get all the items in the table ,it return

LiveData<List<Item>>

Then in the viewModel i want to apply selection(true) accordig to the Mutablelivedata selectionId, the selection id contain MutableLiveData<Long> (it contain an id in the LiveData<List<Item>>)

The MyViewModel.kt code is look like this


class MyViewModel(val repository: Repository) : ViewModel() {
    ..........
    ......

    val selectionId: MutableLiveData<Long> by lazy {
        MutableLiveData<Long>()
    }

    fun setSelectionId(id: Long) {
        selectionId.postValue(id)
    }

    ..........
    ......

    val itemLiveList: LiveData<List<Item>> = liveData(Dispatchers.IO) {
        emitSource(repository.getItems())
    }
 }

If it is an List<Item> i can do somethig like this


 val ItemWithSelection: List<Item> = repository.getItems().apply {
        this.forEach {
            if (it.id == selectionId) {
                it.selection = true
            }
        }
    }

but i don't know how to achieve this using Mediator LiveData . Please help me


Solution

  • I don't understand everything in your code, for example I have never seen a function called liveData(CoroutineDispatcher). But do you mean you want something like this?

    val listWithoutSelection = liveData(Dispatchers.IO) {
        emitSource(repository.getItems())
    }
    
    val listWithSelection = MediatorLiveData<List<Item>>().apply {
        addSource(listWithoutSelection) { updateListSelection() }
        addSource(selectionId) { updateListSelection() }
    }
    
    fun updateListSelection() {
        listWithSelection.value = listWithoutSelection.value?.map {
            if (it.id == selectionId.value)
                it.copyWithSelection(true)
            else
                it
        }
    }
    

    The copyWithSelection could be easily done with Kotlin data classes. It is not needed dependent on whether you want to modify the object you get from the database. If you only use that object here, you could just always reset the selection of the others to false and then you can keep the object and you don't need a copy.