Как отправить несколько команд из MVVM в View с помощью класса SingleLiveEvent - PullRequest
0 голосов
/ 12 декабря 2018

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

Затем я нашел концепцию команд, использующих класс SingleLiveEvent, и нашел еехорошо, потому что это напоминает мне ту же модель при использовании Xamarin и mvvvm от Microsoft.Одна из (немногих) хороших вещей, которые есть в работе с xamarin;)

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

sealed class CustomCommands{
    class CustomCommand1 : CustomCommands()
    class CustomCommand2() : CustomCommands()
    class CustomCommand3() : CustomCommands()
    class CustomCommand4() : CustomCommands()
    class CustomCommand5() : CustomCommands()
}

Затем в моем viewModel у меня есть объект команды SingleLiveEvent:

 class CustomViewModel...{
val commands: SingleLiveEvent<CustomCommands> = SingleLiveEvent()

 private fun doComplicatedThingsOnTheUI() {

   GlobalScope.launch(Dispatchers.IO) {

  if (someConditionsInvolvingRestRequestsAndDatabaseOperations()){
                commands.postValue(CustomCommands.CustomCommand1())
                commands.postValue(CustomCommands.CustomCommand2())
            } else {
                commands.postValue(CustomCommands.CustomCommand3())            
                commands.postValue(CustomCommands.CustomCommand4())
            }

      commands.postValue(CustomCommands.CustomCommand5())
   }


}

}

А в Activity / Fragment у меня есть наблюдатель для команд, который должен реагировать на каждую команду и выполняет работу:

class MainActivity...{

viewModel.commands.observe(this, Observer { command ->
            Rlog.d("SingleLiveEvent", "Observer received event: " + command.javaClass.simpleName)
            when (command) {
Command1->doSomething1()
Command2->doSomething2()
}

}

Ну, проблема в том, что представление обычно получает толькопоследняя команда (Command5).Но поведение зависит от уровня API Android SDK.По API 16, представление получает последнюю команду.В Api 28 представление обычно получает первую и последнюю команду (например, Command1 и Command5, но не Command2).

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

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

Может быть, у меня есть совет для меня.Любая помощь будет приветствоваться.

Заранее спасибо.

1 Ответ

0 голосов
/ 12 декабря 2018

Мне кажется, я нашел обходной путь, который, кажется, работает (я тестировал его всего пару часов).

Дело в том, что я использую "command.postValue (XXX)", потому чтоэтот кусок кода выполняется внутри процедуры, то есть в другом потоке.Из-за этого я не могу использовать command.value напрямую.

Но дело в том, что с помощью command.value = Command1 () это работает.Я имею в виду, что представление получает все отправленные команды, и, что очень важно, в том же порядке, в котором они были отправлены.Из-за этого я написал небольшую функцию для отправки команд в пользовательский интерфейс, переключая поток.

Я не уверен, что это правильно, я новичок в сопрограммах Kotlin и должен признать, что япока не очень хорошо понимаю их:

    private suspend fun sendCommandToView(vararg icommands: CustomCommands) = withContext(Dispatchers.Main) {
    icommands.forEach {
        commands.value = it
    }
}

А потом я посылаю команды

sendCommandToView(CustomCommand1(),CustomCommand2(),CustomCommand5())

Кажется, это работает.Думаю, что метод «post» будет работать аналогичным образом, но это не так.

С уважением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...