Каков наилучший способ передать объекты в "обзорную модель" в MVVMCross?

У меня есть ViewModel, который содержит команду, у которой есть свойство Players, которое является списком объектов Player. В TeamView команда загружена, поэтому данные игрока уже находятся в памяти.

Каков наилучший способ передать данный выбранный экземпляр класса Player в PlayerView?

Проблема заключается в том, что конструкторы MVVMCross ViewModel могут содержать только строковые свойства в текущей версии.

У меня есть следующие идеи:

  • Передайте идентификатор выбранного игрока и назначьте свойство Team.Players как ViewModel для PlayerView. Это может быть разумным решением, если выбранный игрок является только сфокусированным игроком в PlayerView, а PlayerView действительно является "игровым" представлением, в котором пользователь может провести пальцем между другими игроками команды.

  • Имейте ASP.Net MVC, например службу ViewBag, которая может переносить данные только между действиями навигации, в словаре, подобном хранилищу, и параметр, переданный в PlayerView, представляет собой "viewbag: PlayerId123", который является специальным ключом, указывающим на экземпляр класса.

  • Сериализуйте выделенный объект в строку и передайте его как сериализованный объект в конструктор. Это возможно, но мне это не нравится.

Ответ 1

В общей навигации 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, операционная система может бесплатно удалить ваше приложение из памяти и затем перезапустить его позже. Это называется Tombstoning на WP7, но похоже, что это называется Убито на Android.

В этих случаях операционная система может перезапустить ваше приложение позже, когда пользователь перейдет обратно. Этот перезапуск будет напрямую направлен на активность, в которой находился пользователь в последний раз, и он будет помнить задний стек - это будет до вашего приложения, чтобы должным образом регидратировать любые требуемые объекты обратно в память.

Вот некоторые очень маленькие картинки, объясняющие это...

Android lifecycle from Xamarin docsenter image description here

Подробнее см. Xamarin и MSDN


Для вашего случая с Team/Player вы можете справиться с регидратацией:

  • Реализация ITeamCache в качестве объекта с файловой поддержкой - например, он может использовать JSON файл или базу данных SQLite в качестве постоянного хранилища для данных в памяти.
  • Реализация некоторой логики вашего кода, которая запрашивает данные из сети при необходимости
  • Реализация какой-либо стратегии аварийного перехода на задний план в этих случаях - поскольку эти случаи не случаются так часто во многих приложениях на современных богатых ресурсом телефонах.
  • Просто сбой - хотя это нецелесообразно...

Не удивительно, что многие приложения не очень хорошо справляются с надстройкой...


Примечание. Для небольших объектов ваша опция 3 (сериализация) может работать хорошо - однако это не поможет вам в ситуации, когда происходит регидратация приложения, и затем пользователь переходит от PlayerViewModel к TeamViewModel.


Подробнее о некоторых недавних изменениях в lifecyle для Android в MvvmCross см. http://slodge.blogspot.co.uk/2012/05/android-application-initialization-and.html