Типизированный параметр в лямбде, не распознаваемый связывателем данных при использовании BindingAdapter - PullRequest
0 голосов
/ 08 апреля 2019

Я пытаюсь связать следующие элементы:

xml:

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

viewModel:

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) в классе MyViewModel

Похоже, что механизм связывания не распознает isChecked как Boolean.Я пытался принудительно набрать xml как isChecked:Boolean, но получаю кучу разных ошибок.

Сейчас я заставил это работать, используя Any вместо Boolean, но я чувствую, что это неправильно:

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

и

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

Кто-нибудь знает, как заставить работать правильную сигнатуру функции?

1 Ответ

2 голосов
/ 09 апреля 2019

Согласно документации Binding Adapters : «Обработчики событий могут использоваться только с интерфейсами или абстрактными классами с одним абстрактным методом, как показано в следующем примере:

@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)
      }
  }
}

» В документации БД никогда не указывается, что вы можете использовать лямбды Kotlin в Binding Adapters В этом случае вам нужно создать интерфейс только с одним методом, подобным этому:

interface CustomOnCheckedListener {
    fun onChecked(isChecked: Boolean)
} 

тогда ваш Binding Adapter:

@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}"
...