在 Android MVVM 架构中显示来自 ViewModel 的对话框

Show Dialog from ViewModel in Android MVVM Architecture

关于具有新架构组件的 MVVM,我有一个问题,如果我的应用程序需要显示例如一个对话框,其中包含我的 VM 中发生的某些操作的 3 个选项,我应该如何实现?谁负责向 Activity/Fragment 发送显示对话框的命令?

UI 相关操作(如打开新活动或显示对话框)是从视图(activity 或片段)触发的,而不是从 ViewModel 触发的。 ViewModel 没有对视图的引用以防止泄漏并保留表示层 "reactive"。

您可以将您的视图(activity 或片段)订阅到 ViewModel 中的一个可观察对象,这样当它发生变化时,您可以从视图中启动您的对话框或新的 activity。

编辑:我写了一篇关于这个的文章,因为它并不简单。一个好的方法是将事件建模为状态的一部分,并使用事件包装器进行导航等操作:https://medium.com/google-developers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

在 Android 中,最常见的从 ViewModel 到视图 (Activity/Fragment) 的通信是通过观察 LiveData 值。在 ViewModel 中设置 MutableLiveData 值并将其作为 LiveData 暴露给视图以供观察。 这在对某些状态变化做出反应时很方便。设置状态持续存在并且相关,直到下一次更改。例如,配置更改很方便,我们的视图状态保留在 ViewModel 中。

但有时这是不可取的 - 使用“短暂”或“无状态”操作 - 只会短暂地改变 UI 的状态并且仅在操作发生时相关 - 例如操作显示一条消息(无论是吐司还是小吃店)——我们不想 re-show 10 分钟后仅仅因为发生屏幕旋转就出现错误消息;或导航操作 - 我们不想在顶部重新打开另一个屏幕。这些可以用 Jose Alcérreca 的回答中描述的 SingleLiveEvent 模式来处理。

我创建了一个小型库,以便于发送此类动作 - 称为“简短动作” - 动作,而不是事件,因为事件是我们做出反应的东西,我们 send/initiate。

你可以在这里查看:

https://bintray.com/vlad-markovic/maven/com.vladmarkovic.briefactions#read

它也是开源的;请随时贡献:

https://github.com/vlad-markovic/AndroidBriefActions

在 Gradle 中导入:

implementation "com.vladmarkovic.briefactions:briefactions:$briefActionsVersion"

在对话框中:

val viewModel =
        ViewModelProvider(context as ViewModelStoreOwner)[MyViewModel::class.java]
viewModel.sendUserAnswer()