在 kotlin 中使用数据绑定时找不到属性 ImageView 的 getter

Cannot find the getter for attribute ImageView while using Databinding in kotlin

我正在尝试使用 Kotlin 学习 数据绑定,并且我能够成功地实现它以编辑文本和文本视图。之后我尝试将它用于图像视图。我目前正在尝试为用户提供一个选项,让他们通过单击图片视图来选择他们的个人资料图片。此代码工作正常,但是当我尝试使用数据绑定适配器将图像设置到视图时,出现以下错误。

Found data binding errors. ****/ data binding error ****msg:Cannot find the getter for attribute 'android:userImage' with value type java.lang.String on de.hdodenhof.circleimageview.CircleImageView. file:/home/parangat-pt-p10/AndroidStudioProjects/ReUsableAndroid/reusable_android/app/src/main/res/layout/activity_signup.xml loc:25:12 - 31:48 ****\ data binding error ****

下面是我的代码。

ImageView的布局代码

<de.hdodenhof.circleimageview.CircleImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center_horizontal"
            android:userImage="@{signup.userImage}"
            android:id="@+id/iv_user"
            android:src="@drawable/profile"/>

型号class代码

    class Signup {
    var userImage=""
    var firstName=""
    var lastName=""
    var phoneNumber=""
    var postCode=""
    var country=""
    var email=""
    var password=""
    var confirmPassword=""
    var isAcceptTerms=false

    @BindingAdapter("android:userImage")
    fun loadImage(view: CircleImageView, imageUrl: String) {
        userImage=imageUrl
        Glide.with(view.context).load(imageUrl).into(view)

    }
}

这就是我在用户选择图像后所做的事情

override fun onSingleImageSelected(uri: Uri?) {
    signupBinding.signup?.loadImage(iv_user,uri.toString())

}

由于这是用 kotlin 编写的,因此无需定义 getter 和 setter 方法,但错误指出未找到 getter 方法。

按照 Enzokie 的建议,我在单独的文件中创建了绑定适配器,如下所示

@BindingAdapter("userImage")
fun loadImage(view: CircleImageView, imageUrl: String) {
    Glide.with(view.context).load(imageUrl).into(view)
}

但我仍然遇到同样的问题。

尝试删除 android TAG

@BindingAdapter("userImage")
fun loadImage(view: CircleImageView, imageUrl: String) {
    userImage=imageUrl
    Glide.with(view.context).load(imageUrl).into(view)

}

<de.hdodenhof.circleimageview.CircleImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center_horizontal"
        app:userImage="@{signup.userImage}"
        android:id="@+id/iv_user"
        android:src="@drawable/profile"/>

使用这个

@BindingAdapter({"bind:userImage"})

而不是这个

@BindingAdapter("android:userImage")

并在 CircleImageView

<de.hdodenhof.circleimageview.CircleImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center_horizontal"
            app:userImage="@{signup.userImage}"
            android:id="@+id/iv_user"
            android:src="@drawable/profile"/>

这是 Loading images with data binding

的好文章

正确的方法

  • 使用 Observable / Live Data.
  • 单独制作一个绑定适配器 class,不要把模型弄乱。
    • 是的,教程就是这样做的,因为它们只是在教你。
    • 只需为整个应用制作一个通用绑定适配器(如android:src)。
  • 不需要使用自定义命名空间,直到你需要它。所以你可以使用 android:src 而不是 android:userImage.
  • 无需在 BindingAdapter 中使用 CircleImageView,使用 ImageView 制作通用适配器,因为 CircleImageViewImageView 的子级。

最终代码

  • 如果您需要手动更改 signup.userImage = "someUrl" 等字段,请使用 Bindablenotify,否则两者都不需要。
  • 如果你使用ObservableField而不是扩展BaseObservableclass,那么你不需要使用Bindablenotify.

Signup.class

class Signup : BaseObservable() {
    @get:Bindable
    var userImage: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.userImage)
        }
}

DataBindingAdapter.kt

 // binding adapter for setting url/uri on ImageView
@BindingAdapter("android:src")
fun setImageUrl(view: ImageView, url: String) {
    Glide.with(view.context).load(url).into(view)
}

layout.xml

<de.hdodenhof.circleimageview.CircleImageView
            ...
            android:src="@{signup.userImage}"/>

现在可以设置binding.signup.userImage = "Url",它会自动折射到UI。

就这些了!

失败原因

当您使用数据绑定时,您希望UI在设置字段后自动更新。那么您的模型应该是以下之一:

在您的情况下,最初您的 URL 是空的 ("")。现在,当您在一段时间后以编程方式设置图像时,UI 不会收到通知,因为您没有像我上面所说的那样使用任何观察选项。

更多信息

两者的区别在于,实时数据是 Android 生命周期感知(Activity/片段/服务)。

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

连同 Khemraj 给出的答案,请确保您已将绑定适配器标记为 @JvmStatic,并且应将其添加到 @BindingAdapter 注释上方。我在 Binding Adapter 注释后添加了 jvmstatic,浪费了一整天。

object ImageBindingAdapter {
@JvmStatic
@BindingAdapter("android:src")
fun setImage(imageView: ImageView, uri: String) {
    Glide.with(imageView.context).load(uri).placeholder(R.drawable.no_image).error(R.drawable.no_image).centerCrop().into(imageView)
}}