Android数据绑定:Kotlin中的@BindingAdapter无法识别lambdas

Вла*_*ков 10 android kotlin android-databinding

这是我的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
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

当我在布局中使用kotlin方法调用分配lambda时,我在构建期间出现了这样的错误:

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 ****
Run Code Online (Sandbox Code Playgroud)

或者如果我通过引用分配方法:

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 ****
Run Code Online (Sandbox Code Playgroud)

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

如何在布局中为Kotlin中的自定义@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
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

变量绑定工作得很好

SE *_*lio 12

简短答案

不要使用Kotlin通用lambda类型,而是使用具有单个方法的接口,该方法既要与返回值也要与方法引用(itemClick)或侦听器(avatarClick)的参数相匹配。您还可以将抽象类与单个抽象方法一起使用,还可以使用匹配的参数和返回类型。

说明

实际上,数据绑定文档从来不提的是,科特林拉姆达工种作为数据绑定监听器或方法的引用,可能是因为引擎盖下这些拉姆达类型转换为科特林的Function1Function2......这是仿制药,因此他们的一些类型的信息并不能使它可执行文件,因此在运行时不可用。

为什么您的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
}
Run Code Online (Sandbox Code Playgroud)


Jua*_*dez 7

我遇到了同样的情况,有效的方法是将其声明为定义其类型的变量,该变量与编译器一起使用

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