【问题标题】:Typed parameter in a lambda not recognized by the data binder when using BindingAdapter使用 BindingAdapter 时数据绑定器无法识别 lambda 中的类型化参数
【发布时间】:2019-04-08 17:20:15
【问题描述】:

我正在尝试绑定以下元素:

xml:

<android.support.v7.widget.SwitchCompat
    ...
    bind:onCheckedChanged="@{(isChecked) -> viewModel.onCheckedChanged(isChecked)}"
    .../>

视图模型:

class MyViewModel() {
    fun onCheckedChanged(isChecked: Boolean) {
        ...
    }
}

使用 BindingAdapter:

@BindingAdapter("onCheckedChanged")
fun bindOnCheckedChanged(view: SwitchCompat, onCheckedChanged: (Boolean) -> Unit) {
    view.setOnCheckedChangeListener(
        { _, isChecked ->
            if (view.isPressed) onCheckedChanged(isChecked)
        }
    )
}

我得到的错误是这个:

数据绑定错误****msg:找不到方法 类中的 onCheckedChanged(java.lang.Object) 我的视图模型

数据绑定器似乎无法将isChecked 识别为Boolean。我试图强制输入像isChecked:Boolean 这样的xml,但我得到了一堆不同的错误。

现在我通过使用Any 而不是Boolean 使其工作,但我觉得这是错误的:

@BindingAdapter("onCheckedChanged")
fun bindOnCheckedChanged(view: SwitchCompat, onCheckedChanged: (Any) -> Unit) {
    ...

fun onCheckedChanged(isChecked: Any) {
    val isSwitchChecked = isChecked as? Boolean ?: return
    ...

有谁知道如何使它工作正确的函数签名?

【问题讨论】:

  • 你试过bind:onCheckedChanged="@{viewModel::onCheckedChanged}"吗?
  • @Fred 我试过了 -> 没用

标签: android kotlin android-databinding


【解决方案1】:

根据Binding Adapters documentation:“事件处理程序只能与具有一种抽象方法的接口或抽象类一起使用,如下例所示:

@BindingAdapter("android:onLayoutChange")
fun setOnLayoutChangeListener(
    view: View,
    oldValue: View.OnLayoutChangeListener?,
    newValue: View.OnLayoutChangeListener?
) {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
      if (oldValue != null) {
          view.removeOnLayoutChangeListener(oldValue)
      }
      if (newValue != null) {
          view.addOnLayoutChangeListener(newValue)
      }
  }
}

" DB docs never specify you can use Kotlin lambdas in Binding Adapters 在这种情况下,您需要创建一个只有一种方法的接口,如下所示:

interface CustomOnCheckedListener {
    fun onChecked(isChecked: Boolean)
} 

然后是你的绑定适配器:

@BindingAdapter("onCheckedChanged")
fun bindOnCheckedChanged(view: SwitchCompat, onCheckedChanged: CustomCheckListener) {
    view.setOnCheckedChangeListener(
        { _, isChecked ->
            if (view.isPressed) onCheckedChanged.onChecked(isChecked)
        }
    )
}

在您的 ViewModel 类中,您需要创建一个与侦听器方法签名相同的函数:

fun onChecked(isChecked: Boolean){
    //some code here
}

在您的 xml 中只需传递对您的函数的引用:

"@{viewModel::onChecked}"

【讨论】:

  • 有趣...但它在 xml 中的外观如何?
  • @RenaudC。我添加了您需要在布局中编写的代码
  • 所以我猜你的界面中的函数是 onChecked() 而不是 doIt(),对吗?
  • @RenaudC。但是这里重要的是引用的函数必须与监听函数的签名相同,幸运的是,如果签名不匹配,编译器会显示错误。
【解决方案2】:

解决方案:(科特林)

使用 lambda参数


| val lambda: (arg1, arg2, ...) -> 类型 |


1️⃣ ➖ Lambda 实现:

MainActivity.kt

val lambda: (TextView?) -> Unit = {
    Log.i(TAG, "lambda: ${it?.text}")
}

2️⃣ ➖ BindingAdapter 实现:

绑定.kt

@BindingAdapter("lambda")
fun View.lambda(block: (TextView?) -> Unit) {
    // Your logic
}

3️⃣ ➖ 使用 DataBinding 和 BindingAdapter:

activity_main.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">

   <data>

       <variable
           name="activityMain"
           type="com.veldan.mvi.ui.activities.MainActivity" />
   </data>

   <View
        lambda="@{activityMain.lambda}"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</layout>

PS。 Vel_daN:爱​​你所做的事情?。

【讨论】:

    猜你喜欢
    • 2018-04-08
    • 2014-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多