安卓数据绑定:Kotlin中的@BindingAdapter无法识别lambda表达式

23

这是我的BindingAdapter

@BindingAdapter(value = *arrayOf("bind:commentsAdapter", "bind:itemClick", "bind:avatarClick", "bind:scrolledUp"), requireAll = false)    
fun initWithCommentsAdapter(recyclerView: RecyclerView, commentsAdapter: CommentsAdapter,
                        itemClick: (item: EntityCommentItem) -> Unit,
                        avatarClick: ((item: EntityCommentItem) -> Unit)?,
                        scrolledUp: (() -> Unit)?) {
    //Some code here
}

initWithCommentsAdapter 是一个顶层函数。

这是我的布局(一个基本部分):

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto">

           <data>
               <variable
                   name="viewModel"
                   type="some.example.path.CommentsViewModel"/>
               <variable
                   name="commentsAdapter"
                   type="some.example.path.CommentsAdapter"/>
           </data>

           <android.support.v7.widget.RecyclerView
                ...
                bind:avatarClick="@{(item) -> viewModel.avatarClick(item)}"
                bind:itemClick="@{viewModel::commentClick}"
                bind:commentsAdapter="@{commentsAdapter}"
                bind:isVisible="@{viewModel.commentsVisibility}"
                bind:scrolledUp="@{() -> viewModel.scrolledUp()}"
            />
</layout>

当我在布局中给lambda赋值时调用kotlin方法,构建过程中出现了以下错误:

请注意:以上内容已经是翻译后的文本,不需要进一步翻译。
e: java.lang.IllegalStateException: failed to analyze: 
java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:cannot find method avatarClick(java.lang.Object) 
in class some.example.path.CommentsViewModel
****\ data binding error ****

或者如果我通过引用赋值方法:

e: java.lang.IllegalStateException: failed to analyze: 
java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Listener class kotlin.jvm.functions.Function1 
with method invoke did not match signature of any method viewModel::commentClick
file:C:\Android\Projects\...\fragment_comments.xml
loc:70:12 - 83:17
****\ data binding error ****

但我有适当类型的方法,而不是Object

问题

如何在布局中为自定义@BindingAdapter分配Kotlin lambda?

编辑

viewModel的相关部分:

class CommentsViewModel(model: CommentsModel): BaseObservable() {
    //Some binded variables here
    ...
    fun commentClick(item: EntityCommentItem) {
        //Some code here
    }

    fun avatarClick(item: EntityCommentItem) {
        //Some code here
    }
    fun scrolledUp() {
        //Some code here
    }
    ...
}

变量绑定工作得很好


你能添加CommentsViewModel的相关部分吗? - tynn
我从viewModel类中添加了一些相关的代码。 - Владимир Широков
与BindingAdapter中的类型相同 - Владимир Широков
你找到解决方法了吗? - Dex Sebas
很遗憾,不是的。我使用了一种解决方法。我只是传递了一个带有一些方法的对象。但那是很久以前的事了。我已经忘记了。 - Владимир Широков
显示剩余2条评论
2个回答

39

简短回答

不要使用Kotlin泛型lambda类型,而是使用一个方法与您的方法引用(itemClick)或侦听器(avatarClick)的返回类型和参数匹配的接口。 您也可以使用一个抽象类,其中包含一个抽象方法,其参数和返回类型也匹配。

解释

实际上,在Databinding文档中从未提到过Kotlin lambda类型作为Databinding监听器或方法引用,可能是因为在幕后这些lambda类型转换为Kotlin的 Function1 Function2 ...这些都是泛型,因此它们的某些类型信息没有传递到可执行文件中,因此在运行时不可用。

为什么您的scrolledUp绑定仍然有效? 因为类型() -> Unit不需要泛型。 它甚至可以使用Runnable工作。

代码

interface ItemClickInterface {
    // method may have any name
    fun doIt(item: EntityCommentItem)
}

@BindingAdapter(
    value = ["commentsAdapter", "scrolledUp", "itemClick", "avatarClick"],
    requireAll = false
)
fun initWithCommentsAdapter(
    view: View,
    commentsAdapter: CommentsAdapter,
    scrolledUp: () -> Unit,            // could have been Runnable!
    itemClick: ItemClickInterface,
    avatarClick: ItemClickInterface
) {
    // Some code here
}

有相关的官方文档吗?如果有,能给我一个链接吗? - Wood

7

我遇到了相同的情况,解决方法是将它声明为变量并定义其类型,这对编译器有效。

val avatarClick:(item: EntityCommentItem)->Unit = {}


这是答案,但缺少更多信息。 - junior
已经有一段时间了,但我相信参数最终会被声明为一个处理程序。avatarClick:(item:EntityCommentItem) - > Unit = {} - Juan Mendez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接