Kotlin/Android DataBinding中高阶函数作为Binding Adapter参数遇栈溢出错误
解决DataBinding中高阶函数作为Binding Adapter参数导致的StackOverflowError
我之前也踩过这个坑!当你在Android DataBinding里把无参高阶函数() -> Unit作为Binding Adapter的参数时,DataBinding的代码生成器很容易陷入递归循环,最终抛出StackOverflowError,而且日志确实没什么有用的提示,特别让人头疼。
问题原因
DataBinding对Kotlin的无参函数类型() -> Unit的代码生成逻辑有缺陷,在解析这种类型时会不断递归生成包装代码,直接把栈撑爆。
两种可行的解决方案
方案1:改用带参数的函数类型
把Binding Adapter里的函数参数改成带View参数的(View) -> Unit,哪怕你实际用不到这个参数,也能打破递归循环:
// 修改后的Binding Adapter @JvmStatic @BindingAdapter("onDelayedClick") fun onDelayedClick(view: View, function: (View) -> Unit) { // 这里实现你的延迟点击逻辑,比如: view.setOnClickListener { Handler(Looper.getMainLooper()).postDelayed({ function(view) // 调用传入的函数 }, 500) } }
XML里的用法可以对应调整(如果你的ViewModel方法不需要参数,也可以忽略View参数):
<View android:id="@+id/test_view" android:layout_width="wrap_content" android:layout_height="wrap_content" app:onDelayedClick="@{(view) -> viewModel.handleDelayedClick()}" />
方案2:使用Java的Function接口代替Kotlin函数类型
DataBinding对Java的函数式接口支持更稳定,直接用kotlin.jvm.functions.Function0<Unit>替换() -> Unit:
@JvmStatic @BindingAdapter("onDelayedClick") fun onDelayedClick(view: View, function: Function0<Unit>) { // 你的延迟逻辑 Handler(Looper.getMainLooper()).postDelayed({ function.invoke() // 调用函数 }, 500) }
XML里的用法不需要改动,还是原来的写法:
<View android:id="@+id/test_view" android:layout_width="wrap_content" android:layout_height="wrap_content" app:onDelayedClick="@{() -> viewModel.handleDelayedClick()}" />
额外注意事项
- 确保你的Binding Adapter所在的类是
object类或者包含companion object(因为用了@JvmStatic注解,需要生成静态方法) - 执行
Build -> Clean Project然后Rebuild Project,清理一下缓存,避免旧的生成代码干扰 - 确认XML里的
app命名空间已经正确声明:xmlns:app="http://schemas.android.com/apk/res-auto"
内容的提问来源于stack exchange,提问作者Eric Bachhuber
相关产品推荐
相关产品推荐

