Наблюдатель за рефакторингом на Android - PullRequest
1 голос
/ 03 августа 2020

Я создаю приложение, и я сделал страницу типа контакта с парой вводимого текста и кнопкой для отправки сообщения. Теперь я хотел сделать кнопку доступной только при соблюдении некоторых критериев, в которых три наиболее важных поля заполнены некоторыми данными (служба, объект и сообщение).

С шаблоном MVVM и двусторонней привязкой данных , он работает нормально, но когда я наблюдаю за данными в фрагменте, с которым связано представление, у меня появляется уродливый код, который выглядит следующим образом:

contactPageViewModel.serviceToContact.observe(viewLifecycleOwner, Observer { service ->
            contactPageViewModel.objectContact.observe(viewLifecycleOwner, Observer { objectContact ->
                contactPageViewModel.message.observe(viewLifecycleOwner, Observer { message ->
                    contact_send_btn.isEnabled = !service.isNullOrEmpty() && !objectContact.isNullOrEmpty() && !message.isNullOrEmpty()
                })
            })
        })

По сути, он проверяет, поля заполнены данными, и если это так, он активирует кнопку, которая работает хорошо.

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

Спасибо.

1 Ответ

1 голос
/ 04 августа 2020

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

Альтернатива, которая сохраняет вашу модель представления как есть состоит в разделении наблюдателей и вызове функции, которая обновляет кнопку в каждом из них.

contactPageViewModel.serviceToContact.observe(viewLifecycleOwner, Observer { service ->
    updateSendButtonEnabled()
})

contactPageViewModel.objectContact.observe(viewLifecycleOwner, Observer { objectContact ->
    updateSendButtonEnabled()
})

contactPageViewModel.message.observe(viewLifecycleOwner, Observer { message ->
    updateSendButtonEnabled()
})

fun updateSendButtonEnabled() {
    val service = contactPageViewModel.serviceToContact.value
    val objectContact = contactPageViewModel.objectContact.value
    val message = contactPageViewModel.message.value
    contact_send_btn.isEnabled = !service.isNullOrEmpty() && !objectContact.isNullOrEmpty() && !message.isNullOrEmpty()
}

НО! Если вы хотите быть максимально верным паттерну MVVM, это все равно плохо, потому что вы делаете logi c в своем представлении. На 100% верным для MVVM является предоставление вашей модели представления единственной переменной liveata, которая сообщает представлению, следует ли включать кнопку. Тогда единственный наблюдатель и единственное, что он делает, должны выглядеть так:

contactPageViewModel.sendButtonEnabled.observe(viewLifecycleOwner, Observer { isEnabled ->
    contact_send_btn.isEnabled = isEnabled
})
...