Наблюдатель двусторонней привязки данных в Android вызывается дважды

Я учусь использовать привязку данных из следующего примера:

https://github.com/ResoCoder/databinding-with-livedata-tutorial

В частности, у меня возникли проблемы со следующим кодом:

https://github.com/ResoCoder/databinding-with-livedata-tutorial/blob/master/app/src/main/java/com/resocoder/databinding/MainActivity.kt

В строке № 29 есть тост:

Toast.makeText(это, это, Toast.LENGTH_SHORT).show()

Если editTextContent изменен программно, тост вызывается дважды. Вы можете воспроизвести это поведение, нажав кнопку с надписью: «ВЫБРАТЬ СЛУЧАЙНЫЙ ФРУКТ ИЗ РЕДАКТИРОВАНИЯ».

В этом примере дважды вызывать наблюдателя расточительно, так как всплывающее уведомление отображается дважды, но в моем приложении той же функции это вызывает серьезную проблему для пользователя, поскольку я выполняю разные действия, если данные изменяются программно по сравнению с пользователем.

Я попытался смягчить проблему, пометив состояние как программное изменение, но посторонний второй вызов приходит после завершения моего кода. Вызов выглядит так, как будто пользователь редактирует текст, поэтому моя программа выполняет действие, как если бы пользователь ввел данные. Я не вижу никакого способа определить разницу между посторонним вызовом и вводом данных пользователем.

Пожалуйста, не предлагайте мне спрятать значение записи и, если оно не изменилось, игнорировать посторонний вызов. Существует законный вариант использования, когда пользователь вводит точно такое же значение обратно в поле.

В идеале найти причину постороннего звонка и устранить ее было бы лучше, чем устранить проблему и повысить эффективность. Менее желательным было бы обходное решение, чтобы я мог игнорировать второй вызов, чтобы мой код работал правильно.

Я подозреваю, что это как-то связано с настройкой адаптера или, возможно, когда/где я устанавливаю наблюдателя, но это предположение.

Спасибо.


comment
Читая между строк из отчета об ошибках Android, посторонние вызовы наблюдения вполне возможны и могут быть исправлены в будущем выпуске.   -  person Mitch    schedule 23.03.2019


Ответы (1)


  • Вот результат того, как я это сделал
  • GIF создан на основе imgur

Gif ==> Как это сделать

  1. внедрить модуль core_android моей библиотеки, конечно, не вся библиотека и не модуль только для этой проблемы но он включает в себя решение этой проблемы, как вы видите на гифке выше.

  2. в файле activity_main.xml

<!-- use the below 2 attributes
1st one ensures single trigger & 2nd one to distinguish the change -->
<EditText
    editText_textTwoWay="@={viewModel.mutableLiveDataEditTextContent}"
    editText_textTwoWay_enableDistinguishChangeCauser="@{true}"/>
  1. в MainActivity.kt
// inside onCreate()

// for dynamic change -> on button click
button.setOnClickListener {
    viewModel.mutableLiveDataEditTextContent.value = "Hello"
}

// for observing the change -> observe live data
viewModel.mutableLiveDataEditTextContent.observe(this, Observer {
    val isUserInputChangeNotDynamicallyChanged = binding.editText
        .getTag(R.id.editText_textTwoWay_isUserInputChangeNotDynamicallyChanged) as? Boolean
    val prefixMsg = when (isUserInputChangeNotDynamicallyChanged) {
        true -> {
            "User Change -> "
        }
        false -> {
            "Dynamic Change -> "
        }
        null -> {
            "UNKNOWN Change -> "
        }
    }
    val msg = prefixMsg + it.toStringOrEmpty()
    toast(msg) // extension fun for showing a Toast
    logError(msg) // to ensure invocation is done once isa.
})
person Mohamed Alaa    schedule 16.01.2020