将对象传递给“导航到"的最佳方式是什么?MVVMCross 中的视图模型? [英] What is the best way to pass objects to "navigated to" viewmodel in MVVMCross?

查看:17
本文介绍了将对象传递给“导航到"的最佳方式是什么?MVVMCross 中的视图模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ViewModel,它包含一个 Team,它有一个 Players 属性,它是一个 Player 对象列表.在 TeamView 中,团队已深度加载,因此玩家数据已在内存中.

将给定的选定 Player 类实例传递给 PlayerView 的最佳方法是什么?

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

我有以下想法:

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

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

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

解决方案

在一般导航中,MvvmCross 只允许在 ViewModel 之间传递字符串.

这样做的原因是导航需要通过 Xaml Uris 或 Android Intent 等机制在平台级别完成.

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

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

this.RequestNavigate(new { teamId, playerId })

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

此代码可能如下所示:

 公共类 TeamViewModel: MvxViewModel, IMvxServiceConsumer{public TeamViewModel(字符串teamId,字符串playerId){var teamCache = this.GetService();Player = teamCache.GetPlayer(teamId, playerId);如果(玩家==空){//todo - 以某种方式处理这个错误!}}公共播放器播放器{得到;放;}}

请注意,上面的代码测试 Player 是否为 null.这是因为您的假设存在问题在 TeamView 中,团队已深度加载,因此玩家数据已在内存中."

问题在于,在 Android 和 WP7 等平台中,操作系统可以自由地从内存中删除您的应用程序,然后再重新启动它.这在 WP7 上被称为 和 MSDN

<小时>

对于您的团队/玩家案例,您可以通过以下方式应对补液:

  • 将 ITeamCache 实现为文件支持的对象 - 例如它可以使用 JSON 文件或 SQLite 数据库作为内存数据的持久存储
  • 在您的代码中实现一些逻辑,以便在需要时从网络重新获取数据
  • 在这些情况下实施一些紧急导航回家策略 - 因为这些情况在现代资源丰富的手机上的许多应用程序中并不经常发生.
  • 只是崩溃 - 虽然这不是可取的...

毫不奇怪,许多应用程序不能很好地处理墓碑...

<小时>

注意 - 对于小对象,您的选项 3(序列化)可以很好地工作 - 但是,这不会帮助您解决应用程序重新生成并且用户然后从 PlayerViewModel 导航回 TeamViewModel 的情况.

<小时>

有关 MvvmCross 中 Android 生命周期的一些最新变化的更多信息,请参阅 http://slodge.blogspot.co.uk/2012/05/android-application-initialization-and.html

I've a ViewModel which contains a Team which has a Players property which is a list of Player objects. Within TeamView the Team is deep loaded, so player data is already in the memory.

What is the best way to pass a given selected Player class instance to a PlayerView?

The problem is that MVVMCross ViewModel constructors can only contain string properties in current version.

I've the following ideas:

  1. Pass the Id of the selected Player and assign the Team.Players property as a ViewModel to the PlayerView. This can be a reasonable solution if the selected player is just the focused player in the PlayerView and the PlayerView is really a "players" view, where the user can swipe between the other team players as well.

  2. Have a ASP.Net MVC like ViewBag service which can carry data only between navigate actions, in a Dictionary like storage, and the parameter passed to PlayerView is a "viewbag:PlayerId123" which is a special key pointing to the class instance.

  3. Serialize the selected object to string and pass it as serialized object to the constructor. It is possible but I don't like this solution.

解决方案

In general navigation, MvvmCross only allows strings to be passed between ViewModels.

The reason for this is that the navigation needs to be done at a platform level via mechanisms such as Xaml Uris or Android Intents.

For the situation you suggest, the general pattern I would typcially use is:

  • that the TeamViewModel gets the team data from the network using an injected ITeamService
  • that the TeamViewModel also uses an injected singleton ITeamCache to cache the Team
  • that the navigation happens via a call like:

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

  • the PlayerViewModel then receives the TeamId and PlayerId in its constructor, and uses the ITeamCache to collect the right player

This code might look like:

 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; }
 }

Notice that the code above tests for whether Player is null. This is because there is a problem with your assumption "Within TeamView the Team is deep loaded, so player data is already in the memory."

The problem is that in platforms like Android and WP7, the operating system is free to remove your application from memory and to then restart it later. This is referred to as Tombstoning on WP7, but just seems to be called Killed on Android.

In these cases, then the operating system may restart your application later when the user navigates back. This restart will go direct to the activity where the user last was, and it will remember the back stack - it will then be up to your application to properly rehydrate any required objects back into memory.

Here are some very small pictures explaining this...

For more detail, see Xamarin and MSDN


For your Team/Player case, you might be able to cope with rehydration by:

  • Implementing the ITeamCache as a file-backed object - e.g. it could use a JSON file or a SQLite database as a persistent store for the in-memory data
  • Implementing some logic in your code that refetches data from the network when needed
  • Implementing some emergency-navigate-back-home strategy in these cases - as these cases don't happen that often in many applications on modern resource rich phones.
  • Just crashing - although this isn't advisable...

It's no surprise, that many applications don't handle tombstoning very well...


Note - for small objects, your option 3 (serialization) can works well - however, this wouldn't help you with the situation where app rehydration occurs and a user then navigates back from a PlayerViewModel to a TeamViewModel.


For more on some of the recent changes on Android lifecyle within MvvmCross, see http://slodge.blogspot.co.uk/2012/05/android-application-initialization-and.html

这篇关于将对象传递给“导航到"的最佳方式是什么?MVVMCross 中的视图模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆