Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with higher order function as a binding adapter

I am running into issues trying to take a function as a parameter in a binding adapter using Kotlin/Android databinding. This example code throws e: error: cannot generate view binders java.lang.StackOverflowError when building with no other useful info in the log.

Here is my binding adapter:

@JvmStatic
@BindingAdapter("onDelayedClick")
fun onDelayedClick(view: View, function: () -> Unit) {
    // TODO: Do something
}

XML:

        <View
            android:id="@+id/test_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:onDelayedClick="@{() -> viewModel.testFunction()}"/>

and method in my ViewModel:

fun testFunction() = Unit

I have been struggling with this for a bit now and nothing I've tried works, so any help is appreciated.

like image 938
Eric Bachhuber Avatar asked Apr 11 '18 20:04

Eric Bachhuber


People also ask

How do you indicate that a method is a binding adapter?

To create a custom binding adapter, you need to create an extension function of the view that will use the adapter. Then, you add the @BindingAdapter annotation. You have to indicate the name of the view attribute that will execute this adapter as a parameter in the annotation.

What are binding adapters?

Binding adapters are responsible for making the appropriate framework calls to set values. One example is setting a property value like calling the setText() method. Another example is setting an event listener like calling the setOnClickListener() method.

What is an inverse binding adapter?

android.databinding.InverseBindingAdapter. InverseBindingAdapter is associated with a method used to retrieve the value for a View when setting values gathered from the View.


1 Answers

Use function: Runnable instead of function: () -> Unit.

Android's data-binding compiler generates java code, to which, your kotlin function's signature looks like void testFunction(), as kotlin adapts Unit as void when calling from java.

On the other hand, () -> Unit looks like kotlin.jvm.functions.Function0 which is a function which takes 0 inputs and returns Unit.INSTANCE.

As you can see these two function signatures don't match, and that's why the compilation fails.

like image 116
Vibin Avatar answered Oct 14 '22 20:10

Vibin