安卓数据绑定 - 无法找到接受类型为'long'的参数的<>的getter。

4

我过去几周一直在使用数据绑定,现在正在尝试为带有“value”属性的自定义视图使用双向数据绑定。

我的问题是,在构建时遇到以下错误:

找不到接受参数类型“long”的<com.twisthenry8gmail.dragline.DraglineView app:value>的getter

据我了解,绑定库将自动使用我的公共setter和getter,但最令人困惑的部分是添加冗余的反向绑定适配器似乎解决了问题?所以我有这样的印象,它使用我的setter而不需要适配器,但对于getter则不是这种情况?

我的自定义视图

class DraglineView(context: Context, attrs: AttributeSet) : View(context, attrs) {
    ...

    var value = 0L
        set(value) {

            draggedValue = value
            field = value
            invalidate()
        }

    ...
}

我在布局文件中的视图

<com.twisthenry8gmail.dragline.DraglineView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:increment="@{viewmodel.type.minIncrement}"
    app:minValue="@{viewmodel.type.minIncrement}"
    app:value="@={viewmodel.target}" />

看似多余的适配器

@InverseBindingAdapter(attribute = "value")
@JvmStatic
fun getValueTest(draglineView: DraglineView): Long {

    return draglineView.value
}

我的属性改变适配器

@BindingAdapter("valueAttrChanged")
@JvmStatic
fun setDraglineListener(draglineView: DraglineView, listener: InverseBindingListener) {

    draglineView.valueChangedListener = {

        listener.onChange()
    }
}
2个回答

3
当我在我的数据对象和自定义NumberPicker之间使用双向数据绑定时,遇到了类似的问题(编译时出现错误消息:Cannot find a getter for <com.shawnlin.numberpicker.NumberPicker app:np_value> that accepts parameter type 'int' )。
我使用的NumberPicker库是https://github.com/ShawnLin013/NumberPicker,根据其文档,应该使用np_value来设置当前值。它可以正确地工作(值被按需初始化),但是双向数据绑定会给我带来上述错误。
然而,将app:np_value更改为android:value(在注释和布局中)解决了这个问题。
在您的情况下,您可以尝试替换:
@InverseBindingAdapter(attribute = "value")
@BindingAdapter("valueAttrChanged")
app:value="@={viewmodel.target}

使用

@InverseBindingAdapter(attribute = "android:value")
@BindingAdapter("android:valueAttrChanged")
android:value="@={viewmodel.target}"

2
问题在于数据绑定系统不知道视图何时更改InverseBindingAdapter不仅描述了如何从视图中检索,还定义了一个可选的事件属性,该属性将接收一个InverseBindingListener实例。默认事件名称是属性名称后缀为“AttrChanged”。
现在让我们看看您的setDraglineListener()适配器。它处理由InverseBindingAdapter添加的valueAttrChanged属性,并接收InverseBindingListener。唯一剩下的事情就是通过调用listener.onChange()来通知侦听器当被更改时;

谢谢你的回答,但我认为它并没有完全回答我的问题。我真正想知道的是为什么需要首先有一个反向绑定适配器?特别是因为似乎在没有适配器的情况下使用setter没有问题,那么为什么需要getter的适配器呢?感谢您的帮助。 - Henry Twist
@HenryTwist 对不起,我没有正确理解你的问题。我更新了我的答案,希望现在能帮到你。如果你还有任何问题,请随时问。 - Valeriy Katkov
1
抱歉如果我表达不清楚,我的原始问题中的所有代码都运行良好并产生了我期望的结果。我困惑的是数据绑定库生成其代码的方式。为了使双向绑定起作用,我认为它必须访问setter、getter以及某种知道值何时更改的方式(监听器)。然而,绑定在不提供setter的绑定适配器的情况下工作,这意味着它必须自动使用匹配的setter。那么为什么它不能像getter一样做到这一点呢?感谢您的耐心! - Henry Twist
1
感谢您的帮助@ValeriyKatkov,我想我只是困惑为什么它可以生成setter,但无法为getter执行相同的操作! - Henry Twist
1
适配器绑定到特定的视图类型,而不仅仅是属性名称。因此,不用担心,可以在不同的视图中使用相同的属性名称。 - Valeriy Katkov
显示剩余3条评论

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