首页 文章

如何使用 SingleLiveEvent 类将多个命令从 MVVM 发送到 View

提问于
浏览
1

我的 Android 应用程序中有一个 ViewModel,它有一些逻辑,视图需要 adjusted/perform 不同的东西,具体取决于该逻辑的结果。起初我尝试专门与观察者一起做,并对 viewmodel 中的数据状态做出反应,但这太复杂了。

然后我使用 SingleLiveEvent 类找到了命令的概念,我发现它很好,因为它在使用 Xamarin 和 microsoft 的 mvvvm 时提醒我相同的模式。使用 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)。但行为取决于 Android SDK 的 api 级别。通过 api 16,视图接收最后一个命令。通过 Api 28,视图通常接收第一个和最后一个命令(例如,Command1 和 Command5,但不接收 Command2)。

也许我理解 SingleLiveEvent 类的功能错误,或整个 Command 事情错误,但我需要一种方法来允许 viewmodel 根据许多对象和变量的状态对视图进行排序。上面的代码只是一个样本,现实比这更复杂。

我不想在 viewmodel 和视图之间使用回调,因为我读到的地方破坏了整个 MVVM 模式。

也许有人对我有建议。欢迎任何帮助。

先感谢您。

1 回答

  • 0

    我想我找到了一个解决方法,似乎有效(我已经测试了几个小时)。

    问题是我正在使用“command.postValue(XXX)”,因为那段代码在一个 couroutine 中运行,也就是说,在其他线程中运行。因为我不能直接使用 command.value。

    但事实是使用 command.value=Command1(),它的工作原理。我的意思是,视图接收发送的所有命令,并且非常重要,其顺序与发送时相同。因此,我写了一个小功能,将命令发送到 UI 切换线程。

    我不确定这是否正确,我是 Kotlin 协同程序的新手,我不得不承认我还不太了解它们:

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

    然后我发送命令

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

    这似乎有效。但是,“post”方法可以以类似的方式工作,但事实并非如此。

    问候。

相关问题