MvvvmCross ShowViewModel加载序列

本文关键字:加载 ShowViewModel MvvvmCross | 更新日期: 2023-09-27 17:59:12

我的ViewModel中有一个排序问题,它似乎与线程有关,但我不太清楚出了什么问题,也不知道我的"修复"是如何修复的。

我有一个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日志告诉我,ShowViewModel在ErrorViewModel上被调用后立即被调用,但只显示初始视图,而不是ErrorView。

为了"解决"这个问题,我可以做两件事中的一件。

我可以在任务中包装对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的内部结构来帮助解决这个问题,我将不胜感激!

MvvvmCross ShowViewModel加载序列

Init方法应该做得很少。CCD_ 2通常用于复制传递到CCD_ 3中的一些导航参数。Start方法用于启动ViewModel,例如调用LoadInitialDataAsync。有关详细信息,请查看应用程序生命周期文档。

基于https://github.com/MvvmCross/MvvmCross/wiki/viewmodel--to-viewmodel-navigation:

当你的应用程序显示ViewModel页面时,比如说FirstViewModel,然后第一个页面可以请求将显示向前移动到新的ViewModel页面,比如SecondViewModel,使用类似的调用

ShowViewModel<SecondViewModel>();

当FirstViewModel发出此请求时,MvvmCross框架将:

  • 在应用程序中找到一个视图用作SecondViewModel的"页面"-通常这将是SecondView
  • 创建此SecondView的新实例
  • 创建一个SecondViewModel,并将其作为新SecondView的DataContext提供
  • 要求操作系统显示SecondView

您的ShowViewModel<ErrorViewModel()被调用,而初始视图尚未显示,这可能是它的问题,并且适合您的调试器行为。

延迟可能会给它足够的时间来显示,而异步任务不会阻止它,所以它会显示,然后显示完成,切换到另一个视图。

一种选择可能是在之前进行初始化,并使用ShowViewModel传递数据,尽管我没有这方面的经验。或者保存错误状态,让视图加载并从视图中调用viewmodel,让它在创建后切换。

虽然我不太喜欢这两种,但这就是为什么我之前通过服务进行初始化,如果失败,在切换到新的视图模型之前会做出反应。

不知道你目前的结构有多复杂,什么效果最好。