Data Binding: ObservableField with lambda value doesn't compile

北城以北 提交于 2019-12-11 10:39:21

问题


I'm trying to define the visibility of the View by calculating the lambda that takes one parameter as an argument. I'm using Kotlin, btw.

In my ViewModel I have:

    val customerPropVisibility: ObservableField<(KProperty1<Customer, *>) -> Int> = ObservableField(
        { _ ->
            // body of the lambda
        })

The binding expression for the View is the following:

     android:visibility="@{vm.customerPropVisibility.invoke(title)}"

vm and title are properly declared as variables in the data tag of the layout.

On compilation, I get two errors:

1) incompatible types: Object cannot be converted to Function1

2) incompatible types: Object cannot be converted to Integer

There is only one error of the first type and several errors of the second type. The number of the errors of the second type is the same as the number of invocations of the lambda in the layout xml file.

My attempts of solving the issue:

Obviously, the error of type 1 can be solved by overriding the get() method of the ObservableField (making the method return Function1 explicitly). This works, but is ugly and should be done by the compiler when it infers the type for customerPropVisibility. Definitely, something is wrong here.

The error of type 2 is a mystery to me, cause the function type (my lambda) explicitly returns Int.

I presume it has something to do with Kotlin/Java interoperability.

If you have stumbled upon the same issue, please share the experience of solving it.

EDIT:

Since this bug is not yet resolved, I use slightly different approach to achieve the same result:

Instead of setting the value of ObservableField to lambda, I set it to function reference (::getVisibility) like so:

fun getVisibility(prop: KProperty1<*, *>): Int = propVisibilityValues[prop] ?: View.GONE
val propVisibilityGetter = ObservableField(::getVisibility)

And whenever the propVisibilityValues changes I notify the propVisibilityGetter:

private val propVisibilityValues = ObservableArrayMap<KProperty1<*, *>, Int>().apply {
    addOnMapChangedCallback(object : ObservableMap.OnMapChangedCallback<ObservableMap<KProperty1<*, *>, Int>, KProperty1<*, *>, Int>() {
        override fun onMapChanged(p0: ObservableMap<KProperty1<*, *>, Int>?, p1: KProperty1<*, *>?) {
            propVisibilityGetter.notifyChange()
        }
    })
}

In XML layout file, the binding expression looks like:

android:visibility="@{vm.propVisibilityGetter.call(title)}"

Overall result: messy in the View Model, but clean binding expressions.

来源:https://stackoverflow.com/questions/47638336/data-binding-observablefield-with-lambda-value-doesnt-compile

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!