Kotlin 自定义属性数据绑定

Kotlin custom attribute databinding

我正在尝试使用 Android DataBinding Library 设置自定义属性 在我的 Kotlin 项目中是这样的:

布局

<ImageView
    android:id="@+id/imgView”
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:layout_gravity="center"
    android:adjustViewBounds="true"
    app:imageUrl="@{segment.url}"/>
                            

代码

class Utils {
    companion object {
        @BindingAdapter("bind:imageUrl")
        @JvmStatic
        fun loadImage(view: ImageView, url:String) 
        {Picasso.with(view.context).load(url).error(R.drawable.error).into(view)}
    }
}

    

    

我得到的运行时错误是:

A BindingAdapter in in <package.Utils.Companion> is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.

有什么解决办法吗?

这仅适用于自定义属性。其余的数据绑定工作正常

尝试调换注释的顺序。它似乎解决了这个问题:

class Utils {
    companion object {
        @JvmStatic @BindingAdapter("imageUrl")
        fun loadImage(view: ImageView, url:String) { ... } 
    }
} 

问题是databindng编译器使用getCompanion().loadImage否则*.
您可以在生成的 com.your.package.databinding.*Binding class

中验证这一点

* 玩了一会儿后,我注意到这与注释的顺序无关,但似乎是随机的。每当我点击 "rebuild" 时它似乎都会改变。这可能是 kapt 或 kotlin 编译器

中的错误

只需将函数保持在顶层,不需要 class 或伴随对象,它将工作,因为 Kotlin 中的顶层函数被翻译成 Class 的静态成员函数,命名为 FileNameKt 除非被 @file:JvmName 注释覆盖

@BindingAdapter("imageUrl")
fun loadImage(view: ImageView, url:String) { ... }

另一种选择是将扩展函数注释为 @BindingAdapter,它将起作用,因为在字节码签名中将完全匹配 DataBindings 期望的签名(生成的方法仍将接受扩展的对象 class作为第一个参数),函数也应该保持在顶层

@BindingAdapter("imageUrl")
fun ImageView.loadImage(url:String) { ... }

另一种选择是将 BindingAdapter 与扩展名 属性 组合,如下所示:

@set:BindingAdapter("visible")
var View.visible
    get() = visibility == VISIBLE
    set(value) {
        visibility = if (value) VISIBLE else GONE
    }

@BindingAdapter("imageUrl") 之后添加 @JvmStatic 解决了我的问题。

例如:

    @BindingAdapter("android:visibility")
    @JvmStatic
    fun setVisibility(view: View, visible: Boolean) {
        view.visibility = if (visible) View.VISIBLE else View.GONE
    }
}

或使用扩展名:

@BindingAdapter("imageUrl")
fun ImageView.setImageUrl(url: String?) {
    Picasso.with(context).load(url).into(this)
}

现在您可以在其他任何地方使用此功能

函数(loadImage)需要放入object(Singleton in java)而不是class并且在@BindingAdapter("imageUrl")之前设置@JvmStatic像这样:

<ImageView
android:id="@+id/imgView”
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:adjustViewBounds="true"
imageUrl="@{segment.url}"/>

   @JvmStatic
   @BindingAdapter("bind:imageUrl")
   fun ImageView.loadImage( url:String) {
Picasso.with(this.context).load(url).error(R.drawable.error).into(this)
}

这对我有用

object ImageUtils {

        @JvmStatic @BindingAdapter("imageUrl")
        fun ImageView.loadImage(url: String?){
                GlideHelper.loadImage(url,this)
        }
}

在 xml 中像这样:

imageUrl="@{file.thumbnailLink}"

这对我有用。请在下面找到它..

加入gradle:

apply plugin: 'kotlin-kapt'

dependencies {
 kapt "com.android.databinding:compiler:3.1.4"
}

在POJO中添加:

companion object {
  @BindingAdapter("image")
    @JvmStatic
         fun loadImage(view: ImageView, imageUrl: String) {

             //am Using Glide
Glide.with(view.context).setDefaultRequestOptions(RequestOptions().circleCrop())
                 .load(imageUrl).into(view)
         }
     }

布局中:

添加bind:image="@{movies.imageUrl}

<ImageView 
  android:id="@+id/imageView"
  android:layout_width="100dp"
  android:layout_height="100dp"
  bind:image="@{movies.imageUrl}/>