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

Я использую двухстороннее связывание данных для обновления объекта LiveData String из моей ViewModel с помощью строки, заданной в EditText:

<android.support.design.widget.TextInputEditText
  android:id="@+id/writeReviewTitle"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="@={viewModel.liveReviewTitle}"
/>

Итак, насколько я понимаю, ViewModel будет иметь свое liveReviewTitle Атрибут обновляется каждый раз, когда текст изменяется в EditText. Я предполагаю, что это происходит через использование TextWatcher или какой-то механизм прослушивания, который позаботился обо мне в библиотеке. Я также подумал, что когда текст необходимо будет обновить, он будет иметь setter называется. Что, похоже, не так! Когда текст меняется, мне нужно сделать еще кое-что в моей ViewModel, поэтому я реализовал пользовательский setter за liveReviewTitle, но это не вызывается (я пробовал отладку). Вот как это выглядит в ViewModel учебный класс:

var liveReviewTitle: MutableLiveData<String> = MutableLiveData()
        set(value) {
            field = value
            customLogicHere()
        }

Пробовал отлаживать это setter но это, кажется, никогда не называется! Что здесь происходит? Чувствует себя немного запутанным. Текст обновляется и сохраняется в ViewModelэто просто setter это не называется.

3 ответа

Решение

Конечно, он никогда не вызывается, вы не устанавливаете новый MutableLiveData, вы устанавливаете новое значение String внутри MutableLiveData (возможно, с setValue).

Однако вы должны иметь возможность перехватывать установленное значение и выполнять настраиваемую логику после установки значения, если вы предоставляете MediatorLiveData вместо MutableLiveData напрямую.

РЕДАКТИРОВАТЬ: следующее должно работать как ожидалось:

val liveReviewTitle: MutableLiveData<String> = MutableLiveData()
private val mediator = MediatorLiveData<String>().apply {
    addSource(liveReviewTitle) { value ->
        setValue(value)
        customLogicHere()
    }
}.also { it.observeForever { /* empty */ } }

Решение @EpicPandaForce правильное, но в EditText двухстороннее связывание может быть получено намного проще. Добавить атрибут afterTextChanged на ваш виджет, как показано ниже:

android:afterTextChanged="@{viewModel::doLogic}"

Тогда в вашем ViewModel класс просто напиши метод:

fun doLogic(s: Editable) { //update Livedata or do other logic }

РЕДАКТИРОВАТЬ

Я пропустил важное примечание к документации. Намного проще (и гораздо больше пропрер) будет:

android:text="@={viewModel.someLivedata}

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

@EpicPandaForce прав насчет вашего сеттера, это для MutableLiveData сам, а не ценность, которую он держит. Так что ваши LiveData должен быть valнет необходимости быть varи фреймворк должен делать правильные вещи, пока вы устанавливаете LifecycleOwner на привязке. Вы можете добавить еще Observer на ваш LiveData вместо пользовательского сеттера, чтобы добавить свою собственную логику.

Другие вопросы по тегам