繁体   English   中英

Kotlin 带有扩展方法的数据绑定

[英]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-androidkotlin-android-extensionskotlin-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM