1
votes

Code A works well, I think the _displayCheckBox.value should be non-null, you can see Image A which is from the prompt of Android Studio.

I think I have initial the value of _displayCheckBox using private val _displayCheckBox = MutableLiveData(false), so I think _displayCheckBox.value will be non-null MutableLiveData.

But Code B cause the error "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Boolean?", why?

Code A

private val _displayCheckBox = MutableLiveData(false)
val displayCheckBox : LiveData<Boolean> = _displayCheckBox

//Switch CheckBox On or Off
fun switchCheckBoxShowStatus(){
    _displayCheckBox.value?.let {
        _displayCheckBox.value = !it
    }
}

Code B

private val _displayCheckBox = MutableLiveData(false)
val displayCheckBox : LiveData<Boolean> = _displayCheckBox

//Switch CheckBox On or Off
fun switchCheckBoxShowStatus(){
   _displayCheckBox.value = ! _displayCheckBox.value // It cause error.
}

Image A

enter image description here

Added Content

I will always get "The value is false" for Code C. So I think _aa.value will be non-null when I use val _aa = MutableLiveData(false), right?

Code C

 val _aa = MutableLiveData(false)
 Log.e("My","The  value is "+_aa.value?:"null ")
1
@Slaw In the case of LiveData, the return type is explicitly @Nullable T because the value actually can be null even if the type is not nullable, where null indicates that no value has been set yet. A return type of Boolean! would not show an error if you treated it as non-nullable.Tenfour04
@Tenfour04 Ah yes, you're right.Slaw

1 Answers

1
votes

LiveData.getValue() is specifically annotated as returning a nullable value, and so Kotlin interprets it as nullable. It is nullable because the value actually is null if it hasn't been set yet.

If you want to toggle its value, you can provide a fallback value for when it's null. And if you give it an initial value when you instantiate it, you know the value will never be used.

Or you could create your own non-nullable BooleanLiveData that enforces an initial value. By subclassing, you can narrow the returned type of getValue from Boolean? to Boolean.

class BooleanLiveData(initialValue: Boolean): MutableLiveData<Boolean>() {
    init {
        value = initialValue
    }

    override fun getValue(): Boolean = super.getValue() ?: false
}

Or you can use StateFlow instead of LiveData. StateFlow enforces an initial value.