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.
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.
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!!
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() = {}
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
}