Android DataBinding:Kotlin 中的@BindingAdapter 无法识别 lambda [英] Android DataBinding: @BindingAdapter in Kotlin does not recognize lambdas

查看:39
本文介绍了Android DataBinding:Kotlin 中的@BindingAdapter 无法识别 lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的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 是一个顶级函数

这是我的布局(必不可少的部分):

This is my layout (an essential part):

<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>

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

When I assign lambda with kotlin method call in the layout, I have such error during building:

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 ****

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

or if I assign method by reference:

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:AndroidProjects...fragment_comments.xml
loc:70:12 - 83:17
**** data binding error ****

但我有正确类型的方法,而不是对象

But I have such methods with proper type, not Object

问题

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

How can I assign Kotlin lambda for custom @BindingAdapter in Kotlin in the layout?

编辑

viewModel 的相关部分:

The relevant part of the 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
    }
    ...
}

变量绑定工作正常

推荐答案

简短回答

不要使用 Kotlin 泛型 lambda 类型,而是将接口与单个方法一起使用,该方法与方法引用 (itemClick) 或侦听器 (itemClick) 的返回类型和参数相匹配代码>头像点击).您还可以将抽象类与单个抽象方法一起使用,也可以使用匹配的参数和返回类型.

Instead of using Kotlin generic lambda types, use interfaces with a single method that matches both return type and parameters of your method reference (itemClick) or your listener (avatarClick). You can also use abstract classes with a single abstract method, also with matching parameters and return type.

说明

实际上数据绑定文档从未提及Kotlin lambda类型用作数据绑定侦听器或方法引用,可能是因为在幕后这些 lambda 类型转换为 Kotlin 的 Function1Function2... 它们是泛型,因此它们的一些类型信息不会使其成为可执行文件,因此在运行时不可用.

Actually the Databinding docs never mention that the Kotlin lambda types work as Databinding listeners or method references, probably because under the hood these lambda types translate to Kotlin's Function1, Function2... which are generics, and thus some of their type information doesn't make it to the executable and therefore is not available at runtime.

为什么你的 scrolledUp 绑定有效?因为输入 () ->Unit 不需要泛型.它甚至可以使用 Runnable.

Why your scrolledUp binding did work though? Because type () -> Unit has no need for generics. It could have worked even with 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
}

这篇关于Android DataBinding:Kotlin 中的@BindingAdapter 无法识别 lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆