[英]Kotlin databinding with extension methods
我正在尝试在 Android 的数据绑定中使用 Kotlin 扩展方法。 例如; 调用 onclick 处理程序。 所以我做了这段代码:
posttest_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<import type="android.view.View"/>
<import type="com.example.test.post.posttest.PostTestItemViewModelExtensionKt" />
<variable
name="viewModel"
type="com.example.test.post.posttest.PostTestItemViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:clickable="true"
android:onClick="@{(view) -> viewModel.clicked(view)}"
>
[...]
PostTestItemViewModel.kt
open class PostTestItemViewModel : ViewModel() {
val postTitle = MutableLiveData<String>()
val postBody = MutableLiveData<String>()
/**
* Binds the required properties/entities to this ViewModel
*/
fun bind(post: Post) {
postTitle.value = post.title
postBody.value = post.body
}
}
PostTestItemViewModelExtension.kt
fun PostTestItemViewModel.clicked(v: View) {
this.postTitle.value = "clicked"
}
因此,当我将 clicked 方法放置在视图模型中时,它会按应有的方式完美运行。 但是,当我将其创建为扩展方法时,编译时出现以下错误:
e: [kapt] 发生异常:android.databinding.tool.util.LoggedErrorException:发现数据绑定错误。 在 class 中找不到方法 clicked(android.view.View)...PostItemViewModel
我已经尝试过不同的方法,例如将android:onclick
标记更改为PostTestItemViewModelExtensionKt
而不是viewModel
。 不幸的是,所有的事情似乎都不起作用。 所以看起来扩展方法是在数据绑定发生后生成的。 有没有办法解决这个问题,还是我仍然做错了什么? 还是无法绑定扩展方法?
我正在使用 Kotlin 版本 1.2.71、gradle 3.2.0,并将databinding { enabled = true }
和kapt { generateStubs = true }
添加到 my.gradle,并添加插件kotlin-android
、 kotlin-android-extensions
和kotlin-kapt
定义。
不幸的是,你不能使用扩展方法作为onClick
回调。
Kotlin中的扩展方法是作为Java静态方法创建的,而Android框架则是期望实例方法。
请注意,在Android Studio中,您可以将Kotlin类反编译为Java,以查看生成的Java代码。
所以,今天(2022 年)我在我的一个项目中有相同的用例,我能够找到一种方法来使用数据绑定和自定义适配器为 android 视图实现自定义点击侦听器。
用例是:
点击事件不应被触发两次或防止用户误点击
我创建了一个名为 ViewExtensions.kt 的文件并添加了以下代码
class DebouncingOnClickListener(
private val intervalMillis: Long,
private val doClick: (() -> Unit)
) : View.OnClickListener {
override fun onClick(v: View) {
if (enabled) {
enabled = false
v.postDelayed(ENABLE_AGAIN, intervalMillis)
doClick()
}
}
companion object {
@JvmStatic
var enabled = true
private val ENABLE_AGAIN =
Runnable { enabled = true }
}
}
@BindingAdapter("singleClick")
fun View.setSingleClick(doClick: () -> Unit) =
setOnClickListener(
DebouncingOnClickListener(
intervalMillis = 5000, //5ms delay for click event
doClick = doClick
)
)
debouncing click 用于延迟给定时间的点击,在 xml 中调用如下所示的点击事件
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"
app:singleClick="@{()->fragment.clicked()}" />
现在我可以在片段和视图模型中监听点击事件,并且点击会延迟给定的时间。
因此,用户不能意外地多次单击该视图。
参考资料: https://proandroiddev.com/ensure-single-click-on-android-butterknife-did-it-right-48ef56153c78
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.