4

MVVM 方法很好并且很成熟。但是想象一下场景:您有一个应用程序页面,用户可以在其中启动一些长时间运行的任务。就像本地和远程数据库的同步。此任务可能很长,只能优雅地中断。然后用户离开页面,转到一些详细信息页面。取消那个长时间的异步操作没有意义,因为应用程序仍在运行。但是突然用户接到一个电话,因此该应用程序被停用。

在我对 MVVM 的(可能过于原始)的理解中,视图模型应该用于控制与模型的交互(尤其是长时间的操作)。但是 View Model 不需要了解应用程序生命周期事件,因为这会限制代码的可重用性(在 Windows 8 上没有 PhoneApplicationService 这样的类)。在这里看到矛盾了吗?VM 启动操作,但不应用于取消操作。

当然,View 可以承担这个责任来处理生命周期事件。所以关于应用程序停用的事件是这样传播的:View -> ViewModel -> (cancels long operation) -> Model. 但是,如果用户已经从 View 导航,并且在该 View 中启动的一些操作仍在运行,则无法再取消它 - View 可以随时处置。

我只想到了一个想法,那就是在 View Models 中处理应用程序生命周期事件。但是,正如我之前所说,我不喜欢这种方法,因为它限制了 View Models 的可移植性。谁能提供更好的解决方案?

4

3 回答 3

4

我只想到了一个想法,那就是在 View Models 中处理应用程序生命周期事件。但是,正如我之前所说,我不喜欢这种方法,因为它限制了 View Models 的可移植性。谁能提供更好的解决方案?

我实际上在这里没有看到问题。在 MVVM 中,ViewModel 传统上是将 View 与 Model 联系起来的“粘合剂”。

为每个平台拥有少量自定义 ViewModel 代码并不一定会限制 ViewModel 其余部分的可移植性,尤其是当它被抽象并包含在每个平台的自己的项目中时。

VM 启动操作,但不应用于取消操作。

这强烈表明 VM应该是取消它的那个。如果虚拟机创建了这些操作,它实际上拥有它们的所有权,这表明它也应该管理它们的生命周期。

于 2013-02-05T18:39:50.003 回答
1

我不确定这是否违反了 MVVM 原则,但我只是这样想。

关于在VM中订阅PhoneApplicationService,有什么理由不采取这种方法吗?

应用程序 -> 视图模型

应用程序是虚拟机的所有者,如果应用程序通过类似于视图对其虚拟机的界面告诉虚拟机激活/停用,虚拟机可以保持可重用性。但是一旦VM在其中订阅PhoneApplicationService,这不是真的吗,这意味着VM依赖于应用程序,这意味着VM和应用程序相互依赖并且限制了可重用性?

关于长时间任务,如果它需要根据应用程序生命周期而不是页面生命周期生存,它可以作为应用程序模型在 App 范围内,或者可以从 VM 共享但不在页面(视图)范围内的东西。

于 2013-02-06T00:35:34.887 回答
0

您给出的描述向我表明,缺少抽象层。

尤其是:

您的 ViewModel 当然可以启动影响模型的长期运行的事件,但它们对这些长期运行的事件没有任何所有权。这是完全正确的,不应该被打破。如果您启动一个长时间运行的事件(并且您的数据库同步示例在这里非常好),那么模型应该处理这个。

这里缺少的部分是我相信的模型。当有影响模型的长时间运行的任务时,有一个单独的层来处理这些任务。Transaction为了简单起见,让我们称呼它们。

所以:你在模型域中开始你的长期运行的任务。然后模型执行此任务,如果一切正常并且没有被某些用户或系统交互中断,则可以将任务数据应用于模型(或者可以提交事务)。

如果用户或系统以某种方式取消任务,则模型中的任何数据都不应更改。模型本身不会改变!

另一方面,如果模型成功更改,则应通知 ViewModel 并更新视图。但这只是您在这里拥有的两个主要执行分支之一。它就是你的 MVVM 和 ViewModel 实现可能已经处理的那个。

总体:您的视图模型应该启动和取消在模型上运行的任务,但它不需要特别控制它们的生命周期。如果您提出取消长时间运行的任务的可能性,您可以触发取消事件,但应该优雅地结束模型中的任务。

于 2013-02-05T19:35:19.373 回答