Прямая передача данных и двусторонняя привязка данных: пользовательский установщик не вызывается
Я использую двухстороннее связывание данных для обновления объекта 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
вместо пользовательского сеттера, чтобы добавить свою собственную логику.