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

查看:891
本文介绍了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:\Android\Projects\...\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)或侦听器(avatarClick)的参数相匹配. 您还可以将抽象类与单个抽象方法一起使用,还可以使用匹配的参数和返回类型.

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天全站免登陆