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

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

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

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

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

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

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

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


person Attila Hajdrik    schedule 18.05.2012    source источник


Ответы (1)


В общей навигации MvvmCross позволяет передавать только строки между ViewModels.

Причина этого в том, что навигация должна выполняться на уровне платформы с помощью таких механизмов, как Xaml Uris или намерения Android.

Для ситуации, которую вы предлагаете, я бы обычно использовал общий шаблон:

  • что TeamViewModel получает данные команды из сети с помощью введенного ITeamService.
  • что TeamViewModel также использует внедренный singleton ITeamCache для кэширования Team
  • что навигация происходит с помощью вызова, например:

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, но кажется, называется Killed на Android.

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

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

Жизненный цикл Android из документов Xamarinвведите здесь описание изображения

Дополнительные сведения см. в разделах Xamarin и MSDN


В случае вашей команды/игрока вы можете справиться с регидратацией следующим образом:

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

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


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


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

person Stuart    schedule 18.05.2012
comment
Спасибо за ответ, Стюарт, это имеет смысл, нам повезло, что у нас уже есть база данных SQLite на стороне клиента, поэтому перезапуск приложения не представляет сложности, только ITeamCache должен его поддерживать. Я с радостью принимаю это как ответ :-) - person Attila Hajdrik; 19.05.2012
comment
Что-то вроде примера конференции должно показать вам то, что я обычно делаю github.com/slodge/MvvmCrossConference - person Stuart; 19.05.2012
comment
Обновлены параметры, разрешенные в последнем коде vnext — см. slodge.blogspot.co.uk/2013/01/ - person Stuart; 11.01.2013