2012-05-18 4 views
11

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

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

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

Я следующие идеи:

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

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

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

ответ

13

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

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

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

  • что 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; } 
} 

Обратите внимание, что код выше тестов для ли игрока null. Это связано с тем, что существует проблема с вашим предположением: «В TeamView команда загружена глубоко, поэтому данные игрока уже находятся в памяти».

Проблема в том, что на таких платформах, как Android и WP7, операционная система может бесплатно удалить ваше приложение из памяти и затем перезапустить его позже.Это называется Tombstoning на WP7, но, похоже, на Android, похоже, называется Killed.

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

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

Android lifecycle from Xamarin docsenter image description here

Более подробно см Xamarin и MSDN


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

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

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


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


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

+1

Спасибо за ответ Стюарт это имеет смысл, нам повезло, что у нас уже есть база данных SQLite на стороне клиента, так перезапуск приложения не имеет проблем, только ITeamCache должен его поддерживать. Я с радостью принимаю это как ответ :-) –

+1

Что-то вроде образца конференции должно показать вам, что я обычно делаю https://github.com/slodge/MvvmCrossConference – Stuart

+0

Такое богатое объяснение! Благодарю. – Askolein