我的ViewModel中存在一个排序问题,这似乎与线程相关,但我无法确定我们的错误或我的修复方式#34;正在修理它。
我有一个ViewModel需要调用异步方法来加载其初始数据。我正在调用MvvmCross自动调用的Init方法的异步方法。如果由于任何原因加载失败我想显示错误屏幕,但在Init调用的方法内调用ShowViewModel不会产生预期的结果。 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日志告诉我在初始ViewModel上调用ShowViewModel之后立即调用ShowViewModel,但只显示初始View,而不是ErrorView。
To&#34; fix&#34;我可以做两件事之一。
我可以在Task.Run中包装对LoadInitialDataAsync的调用:
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;
}
}
这些更改中的任何一个都会产生所需的结果 - 如果在加载期间发生了错误,则ErrorViewModel会显示其视图。
问题是,我不相信这个问题,因为我不了解谚语中出了什么问题,因此不知道这个问题有多强大。这似乎是一个随意的计时事物,将在最不方便的时候在未来的某个时刻再次破裂。
如果有人能够理解MvvmCross的内部结构,那么我很感激!
答案 0 :(得分:3)
Init
方法应该做的很少。 Init
通常用于复制传递到ShowViewModel<TViewModel>()
的一些导航参数。 Start
方法是您打算进行ViewModel启动的方法,例如调用LoadInitialDataAsync
。有关详细信息,请查看App Lifecycle documentation。
答案 1 :(得分:0)
基于https://github.com/MvvmCross/MvvmCross/wiki/viewmodel--to-viewmodel-navigation:
当您的应用显示ViewModel页面时,请说出FirstViewModel 第一页可以请求将显示向前移动到a 新的ViewModel页面,通过使用如下调用来说SecondViewModel:
ShowViewModel<SecondViewModel>();
当FirstViewModel发出此请求时,则为MvvmCross 框架将:
- 找到一个视图,用作应用内SecondViewModel的“页面” - 通常这将是SecondView
- 创建此SecondView的新实例
- 创建SecondViewModel并将其作为新SecondView的DataContext提供
- 要求操作系统显示SecondView
您的ShowViewModel<ErrorViewModel()
被调用,而初始View尚未显示,这可能是它的问题,并且适合您的调试器行为。
延迟使得它可能有足够的时间显示并且异步任务没有阻止它,所以它显示,然后显示完成并切换到另一个视图。
一个选项可能会在使用ShowViewModel之前进行初始化并传递数据,尽管我没有这方面的经验。 或保存错误状态,让视图加载并从视图中调用viewmodel,让它在创建后切换。
虽然我不喜欢其中任何一个,这就是为什么我之前通过服务进行初始化,如果它在切换到新的viewmodel之前失败了。
Dunno你当前的结构有多复杂,最好的结果是什么。