2016-07-28 8 views
3

У меня проблема с упорядочиванием в моей модели ViewModel, которая, похоже, связана с потоком, но я не могу понять, что происходит, или как мое исправление исправляет это.MvvmCross ShowViewModel последовательность загрузки

У меня есть ViewModel, которому необходимо вызвать метод async для загрузки своих исходных данных. Я вызываю метод async из метода Init, который MvvmCross вызывает автоматически. Если по какой-либо причине загрузка не удалась, я хочу показать экран «Ошибка», но вызов ShowViewModel внутри метода, вызванного Init, не приводит к ожидаемому результату. ShowViewModel вызывается правильно, но, следуя этому в отладчике, кажется, что ErrorViewModel показывает, что исходная ViewModel/View закончила загрузку, поэтому она загружается, но не появляется, поскольку она переписывается исходным ViewModel.

Вот упрощенная версия кода загрузки:

public async Task Init() 
{ 
    await LoadInitialDataAsync(); 
} 

protected async Task LoadInitialDataAsync() 
{ 
    var loadResult = await LoadSomeStuffAsync(); 
    if (loadResult.IsBadNews) 
    { 
     ShowViewModel<ErrorViewModel>(); 
     return; 
    } 
} 

Журналы MvxTrace говорят мне, что ShowViewModel вызывается ErrorViewModel сразу после того, как он называется на начальном ViewModel, но только начальный вид шоу, а не ErrorView.

Чтобы исправить это, я могу сделать одну из двух вещей.

можно обернуть вызов LoadInitialDataAsync в Task.Run:

await Task.Run(async() => 
{ 
    await LoadInitialDataAsync(); 
}); 

Или я могу добавить небольшую задержку перед внутренним вызовом ShowViewModel:

protected async Task LoadInitialDataAsync() 
{ 
    var loadResult = await LoadSomeStuffAsync(); 
    if (loadResult.IsBadNews) 
    { 
     await Task.Delay(1); 
     ShowViewModel<ErrorViewModel>(); 
     return; 
    } 
} 

Любой из этих изменений производит желаемый результат - если во время загрузки происходит Bad Thing, ErrorViewModel показывает свое представление.

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

Если кто-то хорошо понимает внутренности MvvmCross, чтобы помочь в этом, я был бы признателен!

+0

Не могли бы вы предоставить репо/образец, который воспроизводит эту проблему? Использование упрощенной версии, похоже, не вызывает такой проблемы. – Plac3Hold3r

+0

У меня есть такая же проблема, о которой никто не знает «ответы». Проблема в том, что в вашем проекте CORE у вас есть какая-то задача, которую вам нужно ждать, и вы хотите отобразить «загрузчик» во время этого ожидания? Правильно? Вы нашли решение для этого? – Ph0b0x

ответ

3

Init способ должен сделать очень немного. Init обычно используется для копирования некоторых параметров навигации, переданных в ShowViewModel<TViewModel>(). Метод Start - это то, где вы планируете запускать ViewModel, например, вызывать LoadInitialDataAsync. Пожалуйста, просмотрите App Lifecycle documentation для получения дополнительной информации.

+0

Спасибо, документация полезна. Тем не менее, я попытался использовать Start() вместо Init(), и поведение точно такое же. –

0

на основе https://github.com/MvvmCross/MvvmCross/wiki/viewmodel--to-viewmodel-navigation:

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

ShowViewModel<SecondViewModel>(); 

Когда FirstViewModel делает этот запрос, то рамки MvvmCross будет:

  • Найдите View, чтобы использовать в качестве «страницы» для SecondViewModel внутри приложения - как правило, это будет SecondView
  • Создать новый экземпляр этого SecondView
  • Создать SecondViewModel и предоставить его в качестве DataContext для нового SecondView
  • Задать операционную систему, чтобы отобразить SecondView

ShowViewModel<ErrorViewModel() для вас будет вызываться, в то время как первоначальный View hasnt показали еще, что может быть ISS ue для него и будет соответствовать вашему поведению отладчика.

Задержка дает достаточно времени для показа, и задача async не блокирует его, поэтому он показывает, затем показ заканчивается, и он переключается на другое представление.

Один вариант, вероятно, должен был выполнить инициализацию до и передать данные с помощью ShowViewModel, хотя у меня нет опыта с этим. Или сохраните состояние ошибки, давайте загрузите представление и вызовите viewmodel из представления, чтобы он переключался после создания.

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

Не знаю, насколько сложна ваша нынешняя структура и что будет лучше всего работать.