MVVMCross中将对象传递给“导航到”视图模型的最佳方法是什么?

12

我有一个ViewModel包含一个Team,这个Team有一个Players属性,是一个Player对象列表。在TeamView中,Team被深度加载,所以player数据已经在内存中。

如何将选定的Player类实例传递给PlayerView是最好的方式?

问题在于,在当前版本中,MVVMCross ViewModel构造函数只能包含字符串属性。

我有以下几个想法:

  1. 传递所选Player的ID并将Team.Players属性作为ViewModel分配给PlayerView。如果所选的球员只是PlayerView中的焦点球员,并且PlayerView确实是一个“players”视图,其中用户也可以在其他团队球员之间滑动,那么这可能是一个合理的解决方案。

  2. 拥有类似于ASP.Net MVC的ViewBag服务,它只能在导航操作之间携带数据,在类似于字典的存储中,传递给PlayerView的参数是“viewbag:PlayerId123”,这是指向类实例的特殊键。

  3. 将所选对象序列化为字符串,并将其作为序列化对象传递给构造函数。这是可能的,但我不喜欢这个解决方案。

1个回答

13

在一般的导航中,MvvmCross仅允许在ViewModels之间传递字符串。

原因是导航需要通过平台级别的机制(如Xaml Uris或Android Intents)完成。

对于您提出的情况,我通常使用的一般模式是:

  • TeamViewModel使用注入的ITeamService从网络获取团队数据
  • TeamViewModel还使用注入的单例ITeamCache来缓存团队
  • 导航通过调用以下方式进行:

this.RequestNavigate<PlayerViewModel>(new { teamId, playerId })

  • 然后,PlayerViewModel在其构造函数中接收TeamId和PlayerId,并使用ITeamCache收集正确的球员

此代码可能如下所示:

 public class TeamViewModel 
     : MvxViewModel
     , IMvxServiceConsumer<ITeamCache>
 {
     public TeamViewModel(string teamId, string playerId)
     {
         var teamCache = this.GetService<ITeamCache>();
         Player = teamCache.GetPlayer(teamId, playerId);
         if (Player == null)
         {
             // todo - handle this error somehow!
         }
     }

     public Player Player { get; set; }
 }

请注意,上面的代码测试了Player是否为null。这是因为你的假设“在TeamView中,团队是深度加载的,所以球员数据已经在内存中。”存在问题。
问题在于,在Android和WP7等平台上,操作系统可以自由地从内存中删除你的应用程序,然后稍后重新启动它。这在WP7上被称为Tombstoning,但在Android上似乎只被称为Killed
在这些情况下,操作系统可能会在用户导航回来时稍后重新启动您的应用程序。这个重启将直接进入用户最后停留的活动,并记住回退堆栈 - 然后就由你的应用程序来正确地重新激活任何需要的对象并将其放回内存中。
以下是一些非常小的图片来解释这个问题...

Android lifecycle from Xamarin docs enter image description here

如需更详细信息,请查看XamarinMSDN


针对您的团队/球员情况,您可能可以通过以下方式应对重新启动后的数据恢复问题:
  • 将ITeamCache实现为基于文件的对象 - 例如,它可以使用JSON文件或SQLite数据库作为内存数据的持久存储
  • 在代码中实现一些逻辑,以在需要时从网络重新获取数据
  • 在这些情况下实施一些紧急导航回主页的策略 - 因为在现代资源丰富的手机上,许多应用程序很少出现这种情况。
  • 只是崩溃 - 虽然这并不可取...
很多应用程序处理墓碑状态都不太好,这并不奇怪...
注意:对于小对象,您的第三个选项(序列化)可能很有效 - 但是,这不会帮助您处理应用程序重新启动并且用户从PlayerViewModel导航回TeamViewModel的情况。

如果想了解MvvmCross中Android生命周期的最新变化,请参阅http://slodge.blogspot.co.uk/2012/05/android-application-initialization-and.html


1
感谢您的回答,Stuart。这很有道理。我们很幸运已经拥有了客户端SQLite数据库,因此应用程序重启是易如反掌的,只有ITeamCache应该支持它。我很高兴接受它作为答案 :-) - Attila Hajdrik
1
类似会议示例的东西应该能够展示我通常做的事情,具体请参见 https://github.com/slodge/MvvmCrossConference。 - Stuart
最新的vnext代码中现在允许更新参数 - 请参见http://slodge.blogspot.co.uk/2013/01/navigating-between-viewmodels-by-more.html。 - Stuart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接