Reputation: 1809
I have the following ViewModel with MutableLiveData data
and another LiveData ones
that is derived from data
in a way that it updates its value only if the data.number
is equal to 1.
class DummyViewModel : ViewModel() {
private val data = MutableLiveData<Dummy>()
val ones = data.mapNotNull { it.takeIf { it.number == 1 } }
init {
data.value = Dummy(1, "Init")
doSomething()
}
fun doSomething() {
data.value = Dummy(2, "Do something")
}
}
data class Dummy(val number: Int, val text: String)
fun <T, Y> LiveData<T>.mapNotNull(mapper: (T) -> Y?): LiveData<Y> {
val mediator = MediatorLiveData<Y>()
mediator.addSource(this) { item ->
val mapped = mapper(item)
if (mapped != null) {
mediator.value = mapped
}
}
return mediator
}
I observe ones
in my fragment. However, If I execute doSomething
, I don't receive any updates in my fragment. If I don't execute doSomething
, the dummy Init
is correctly present in ones
and I receive an update.
What is happening here? Why is ones
empty and how can I overcome this issue?
Upvotes: 1
Views: 924
Reputation: 840
Maybe I'm missing something, but the behavior seems like expected to me...
Lets' try to reproduce both cases sequentially.
Without doSomething() :
Livedata
Dummy(1, "Init")
1
, it passes your filter and the fragment receives itWith doSomething():
Livedata
Dummy(1, "Init")
Dummy(2, "Do something")
(LiveData
keeps only the last value, so if nobody observes, the first value is getting lost)2
, the value gets filtered and the fragment receives nothingA little offtopic: it's always good to write tests for ViewModel cases like this, because you'll be able to isolate the problem and find the real reason quickly.
EDIT: also be aware that your filter is only working on observing, it isn't applied when putting the value into LiveData
.
Upvotes: 2