在 Kotlin 中实现数据绑定框架中的 BindingAdapter 自定义属性
简评:介绍下在 Kotlin 中怎么实现数据绑定(data binding)框架的自定义属性。
使用 Android 的数据绑定框架的 @BindingAdapter 可以很方便的定义在布局文件中使用的自定义属性。一个常见的例子就是使用 Glide 或者 Picasso 来通过 URL 显示图片:
@BindingAdapter("bind:imageUrl")
public static void setImageUrl(ImageView view, String url) {
Glide.with(view.getContext()).load(url).into(view);
}
布局文件:
<ImageView
android:id="@+id/avatar"
android:layout_width="@dimen/photo_size"
android:layout_height="@dimen/photo_size"
android:scaleType="centerCrop"
app:imageUrl="@{user.avatarUrl}"/>
上面的例子是用 Java 实现,可以看到方法必须是 static 的。
但在 Kotlin 中呢?虽然 Kotlin 没有了 static 关键字,但 Kotlin 对方法定义的限制是要比 Java 少的,比如一个方法可以在类外被定义。
将 Kotlin 的方法定义在文件里,而不包含任何类:
@BindingAdapter("imageUrl")
fun setImageUrl(imageView: ImageView, url: String?) {
Glide.with(imageView.context).load(url).into(imageView)
}
Extension functions
在 Kotlin 中我们还可以进一步简化这段代码,也就是通过 extension function 来扩展 ImageView(其实,Java static 方法和 Kotlin extension 方法,最后都是相同的字节码)。
@BindingAdapter("imageUrl")
fun ImageView.setImageUrl(url: String?) {
Glide.with(context).load(url).into(this)
}
Properties
作者在自己的 Android 项目中经常定义的两个 BindingAdapter:
@BindingAdapter("visibleOrGone")
fun View.setVisibleOrGone(show: Boolean) {
visibility = if (show) VISIBLE else GONE
}
@BindingAdapter("visible")
fun View.setVisible(show: Boolean) {
visibility = if (show) VISIBLE else INVISIBLE
}
这样做主要是为了将 View 的可见性状态变为布尔值,方便使用,而不是原本的 Int 类型(VISIBLE, INVISIBLE 和 GONE)。
app:visibleOrGone="@{state.myBoolean}"
虽然,上面使用了 extension function,但在 Kotlin 中我们其实不需要去写 setter,我们可以用 properties,并在 BindingAdapter 前面加上 set 前缀来实现。
@set:BindingAdapter("visibleOrGone")
var View.visibleOrGone
get() = visibility == VISIBLE
set(value) {
visibility = if (value) VISIBLE else GONE
}
@set:BindingAdapter("visible")
var View.visible
get() = visibility == VISIBLE
set(value) {
visibility = if (value) VISIBLE else INVISIBLE
}
这样写在布局文件中的用法没有什么区别,同样是 app:visibleOrGone 和 app:visible。在 Kotlin 代码中也可以很方便的设置:
if (!myView.visibleOrGone) {
myOtherView.visible = true
}
总结
数据绑定框架中的自定义属性是非常有用的,可以简化很多逻辑。而通过 Kotlin 来实现的话可以有多种方式,可以根据实际情况来选择最适合的方式。
原文:Custom attributes using BindingAdapters in Kotlin
日报扩展阅读: