#android #android-databinding
#Android #android-привязка данных
Вопрос:
У меня есть три TextInputEditText
представления в моем макете, где пользователь может вводить определенную информацию.
По щелчку Button
эта информация сохраняется в моей базе данных.
После того, как пользователь нажмет на это Button
, я хочу очистить все TextInputEditText
поля.
Прямо сейчас я делаю это с помощью жесткого кодирования:
private fun clearAllEditTextFields() {
Timber.d("clearAllEditTextFields: called")
binding.bookTitleEditText.text = null
binding.bookAuthorEditText.text = null
binding.bookPageCountEditText.text = null
}
Поскольку это плохо, я хотел бы использовать динамический for each
цикл для идентификации всех представлений TextInputEditText
известного типа binding
и очистки их содержимого:
private fun clearAllEditTextFields() {
Timber.d("clearAllEditTextFields: called")
for (view in binding.views) {
if (view is TextInputEditText) {
view.text = null
}
}
К сожалению, такого поля нет binding.views
.
Есть ли еще способ добиться этого или чего-то с теми же свойствами?
Что я пробовал до сих пор
Я использовал BindingAdapter
. В моем Util
классе, куда идут все мои функции расширения, я создал EditText
функцию расширения clearText
, аннотированную как BindingAdapter
и JvmStatic
:
@JvmStatic
@BindingAdapter("clearText")
fun EditText.clearText(@NotNull shouldClear: Boolean) {
Timber.d("clearText: called")
if (shouldClear) text = null
}
В XML:
<com.google.android.material.textfield.TextInputEditText
android:id="@ id/book_title_edit_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:imeActionId="100"
android:imeOptions="actionNext"
android:inputType="text"
android:text="@={viewModel.bookTitle}"
app:clearText="@{viewModel.clearAllEditTextFields}"
/>
В моем ViewModel
классе я создал a var clearAllEditTextFields = false
, который изменяется в clearAllEditTextFields()
функции, которая вызывается внутри моего ViewModel
:
...
var clearAllEditTextFields = false
clearAllEditTextFields()
...
private fun clearAllEditTextFields() {
Timber.d("clearAllEditTextFields: called")
clearAllEditTextFields = true
}
Согласно Logcat, моя функция расширения вызывается при ViewModel
инициализации my. Однако при clearAllEditTextFields()
вызове он не запускает новый вызов функции расширения.
Ответ №1:
for
Не существует простого цикла для перебора представлений в binding
объекте, и вы можете попробовать следующее, чтобы сохранить свой код в сознании.
Функции области видимости
binding.apply{
bookTitleEditText.text = null
bookAuthorEditText.text = null
bookPageCountEditText.text = null
}
функции области видимости хороши, если просмотров мало, и в итоге мы получаем довольно большой boiler-plate
код, если количество просмотров велико, и в этих случаях я думаю Binding-Adapter
, что это был бы хороший выбор
@BindingAdapter("clear_text")
fun EditText.clearText(shouldClear : Boolean?){
shouldClear?.apply{
if(shouldClear)
text = null
}
}
ViewModel
private val _shouldClear = MutableLiveData<Boolean>()
val shouldClear : LiveData<Boolean>
get() = _shouldClear
fun setClearStatus(status : Boolean){
_shouldClear.value = status
}
//since clearing a text is an event and not state, reset the clear_status once it's done
fun resetClearStatus(){
_shouldClear.value = nul
}
XML
<EditText
......
app:clear_text = "@{yourViewModel.shouldClear}"
...... />
ActivityClass
...
binding.lifecycleOwner = this
...
private fun clearAllEditTextFields() {
yourViewModel.setClearStatus(true)
yourViewModel.resetClearStatus()
}
Редактировать:
добавьте binding.lifecycleOwner = this
свой класс activity и используйте его для наблюдения за LiveData с привязкой данных. Представление будет отслеживать изменения текста во время выполнения.
Комментарии:
1. Спасибо за ответ. Функция области видимости также не является хорошей практикой, поскольку вам также приходится обновлять ее всякий раз, когда вы добавляете новое
EditText
. Ваш второй метод звучит хорошо, но он не работает, так как изменениеshouldClear
не вызывает вызоваclearText()
. Функция вызывается только один раз, когда макет раздувается.2. возможно, что-то не так с вашей стороны, загрузите код того, что вы пробовали до сих пор
3. адаптер привязки получает уведомление каждый раз, когда изменяется базовое исходное значение
4. вы назначили lifecycleowner объекту привязки?
5. Нет, это
JvmStatic
то, для чего нужно. У меня есть это в моемUtil
классе, где я хотел бы его сохранить. Иbinding
в этом классе нет.