简体   繁体   中英

Changing value of a LiveData Calendar do not trigger Observer

In the fragement I display a Date from a Calendar object. This date is got from the viewModel of the fragement and it's a live date:

private val _theDate = MutableLiveData<Calendar>()
val theDate: LiveData<Calendar>
    get() = _theDate

In the viewModel also I have a function that add 1 day to _theDate

fun goToDayAfter() {
    _theDate.value!!.add(Calendar.DATE, 1)
}

This function is called after clicking on a button of the same fragment, and it does not trigger the observer:

viewModel.theDate.observe(viewLifecycleOwner, androidx.lifecycle.Observer { newDate ->
    displayDate(newDate)
})

For more details and after debugging, I believe that _theDate is well changed but the observer is not triggered, If I change to another fragement and come back the new _theDate is changed.

Also if I change the method goToDayAfter() to:

fun goToDayAfter() {
    val tmp = _theDate.value!!
    tmp.add(Calendar.DATE, 1)
    _theDate.value = tmp
}

It works!

Why cahnging _theDate directly do not trigger the observer? is it because it s an object and not a premitive? Is there any better solution that to pass by a tmp variable?

For the update to trigger, you have to set the value of the LiveData , like you have discovered, ie by using:

_theDate.value = ...

Othwerwise, if you mutate (ie change) the value that the LiveData points to ( _theDate.value..,add(Calendar.DATE, 1) , it has no way of knowing that the value was changed. That's why no update is triggered.

Prefer immutable objects

I recommend using immutable objects and re-creating them every time you want to change them. With immutable objects it's more difficult to run into this kind of bugs. An added bonus is that the code that observes _theDate cannot change it.

So instead of Calendar , I would use java.time.LocalDateTime . You can use it if you add a dependency to desugar_jdk_libs in your build.gradle file:

coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'

in which case your code would like like this:

fun goToDayAfter() {
    _theDate.value = _theValue!!.plusDays(1)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM