Issue with higher order function as a binding adapter

不羁的心 提交于 2019-12-04 10:17:58

问题


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.


回答1:


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.




回答2:


In the Event Handling section I came across this line:

In Listener Bindings, only your return value must match the expected return value of the listener (unless it is expecting void)

For more about error :

cannot generate view binders java.lang.StackOverflowError

read this article. hope it will help you!!




回答3:


The declaration () -> Unit suggests a function which takes no input and returns nothing (Unit is the return type in this statement). Your function should look like this:

fun testFunction() = {}



回答4:


Put apply plugin: 'kotlin-kapt' in build.gradle

Then you can create Binding Adapter like

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

And XML Like

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

And VM Like

val testFunction =  {
    // TODO: Do something
}


来源:https://stackoverflow.com/questions/49784193/issue-with-higher-order-function-as-a-binding-adapter

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