efoc
efoc

Reputation: 641

Android LiveData Transformation: Changing LiveData object value

I have one LiveData object that holds a list of Users and I am trying to transfer over the data to another LiveData object to be used elsewhere.

I am using MVVM with Room so I get LiveData from the database and on the ViewModel, I am trying to convert the User object in the LiveData to a Person object to show in the UI.

So I have one variable that is LiveData<List<User>>

class User(var firstName: String, var lastName: String, var age: Integer)

and I am trying to convert it to LiveData<List<Person>> (as an example)

class Person() {

    lateinit var firstName: String

    lateinit var age: Integer
}

and the way I am trying to change them is by using LiveData Transformations.map

ViewModel:

val list2: LiveData<List<User>> = repo.getAll()
var liveList: LiveData<ArrayList<Person>> = MutableLiveData()
liveList = Transformations.map(list2) { list ->
    val newList: ArrayList<Person> = ArrayList()
    list?.forEach {
        val temp = Person()
        temp.firstName = it.firstName
        temp.age = it.age
        newList.add(temp)
    }
    return@map newList
}

but when I run it, it crashes or doesn't update the UI.

Thanks!

Upvotes: 2

Views: 7297

Answers (2)

Haim
Haim

Reputation: 570

The main problem with your code is that it uses var in var liveList: LiveData instead of using val.

You should declare the liveList variable like this:

val liveList = Transformations.map(list2) { list ->
   ...
}

Why?

Generally, a LiveData variable should always be declared with val. The reason is that the purpose of LiveData is to allow us to observe the up-to-date value held by the LiveData. We do it by code like this:

liveList.observe(this) { list ->
    showList(list)
}

With this code, we ensure that the updated list is always shown. Whenever the list value which is held by liveList changes, the UI is updated as a result. But if the liveList itself also changes, the code will only observe the first LiveData of the liveList variable, and the UI will not be updated correctly.

Upvotes: 2

Brandon
Brandon

Reputation: 1417

val liveList = MutableLiveData(repo.getAll().value.orEmpty().map { user ->
        Person(user.firstName, user.age)
})

This would be a more compact way, you could pull out the repo.getAll() call into its own variable if you like

Upvotes: 0

Related Questions