Kotlin two-way data binding bug when property contains `is_`

Viewed 177

There appears to be a significant bug in the way the data binding compiler (or possibly kapt) works.

Two-way data binding fails miserably if the property being bound to is prefixed with is_, with perhaps the world's most useless gradle error message:

cannot generate view binders

Here's an example data class, livedata object and two-way binding converter:

data class BeholdABug(
    var is_useless: Boolean
)

val beholdABugLiveData = MutableLiveData<BeholdABug>()

object Converter {
    fun intToBoolean(int: Int?): Boolean? {
        if(int == null) return false
        if (int == 1) return true
        return false
    }

    @InverseMethod("intToBoolean")
    fun booleanToInt(b: Boolean?): Int? {
        if (b == null) return 0
        if (b) return 1
        return 0
    }
}

Attempting two-way data-binding on the is_useless property fails:

<com.google.android.material.checkbox.MaterialCheckBox
    android:id="@+id/cb_is_useless"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:checked="@={Converter.INSTANCE.intToBoolean(viewmodel.beholdABugLiveData.is_useless)}" />

Simply declaring the binding expression above is enough to cause the compiler to refuse to build the project.

However, if I bind to the is_useless property using only one-way databinding:

<com.google.android.material.checkbox.MaterialCheckBox
    android:id="@+id/cb_is_useless"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:checked="@{Converter.INSTANCE.intToBoolean(viewmodel.beholdABugLiveData.is_useless)}" />

The one-way binding works fine.

There's clearly a bug in the way the is_useless property is evaluated. The compiler is auto-generating getters and setters based on the name of the property. But if the name of the property is prefixed with is_, it appears that either the getter (or more likely, setter) is not properly auto-generated.

Effectively, this means is that you cannot properly create a two-way binding to ANY property named is_{x}.

I have confirmed this by simply changing the name of the property:

data class BeholdABug(
    var useless: Boolean
)

Two-way data-binding works perfectly for enabled. Two-way data-binding fails miserably for is_enabled.

I have exactly ZERO interest in renaming EVERY is_x column in my database to something else, just so it works with data binding in Android. But unless I want to forego two-way binding completely, it appears there is no other choice.

Like nearly everything else in Android, this is absolutely horrific.

0 Answers
Related