挂起 Windows 应用商店应用:调用 MvxSuspensionManager.SaveAsync() 时出错

本文关键字:应用 SaveAsync 出错 MvxSuspensionManager 调用 Windows 挂起 | 更新日期: 2023-09-27 18:30:21

我有一个使用 MvvmCross 的 WinRT 应用程序,我想在其中存储当前会话状态。

在 app.xaml 的 OnLaunch 方法中.cs我向挂起管理器注册了应用程序的内容框架:

...
var setup = new Setup(_contentFrame);
setup.Initialize();
var suspensionManager = Mvx.GetSingleton<IMvxSuspensionManager>() as MvxSuspensionManager;
suspensionManager.RegisterFrame(_contentFrame, "FrameNav");
...         

每当我挂起应用并在 OnSuging 事件处理程序中运行代码时

var suspensionManager = Mvx.GetSingleton<IMvxSuspensionManager>() as MvxSuspensionManager;
await suspensionManager.SaveAsync();

我得到以下异常。

Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManagerException "MvxSuspensionManager failed"
at Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManager.<SaveAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at ****App.xaml.cs:line 129
System.Runtime.InteropServices.COMException "Unbekannter Fehler
"
at Windows.UI.Xaml.Controls.Frame.GetNavigationState()
at Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManager.SaveFrameNavigationState(Frame frame)
at Cirrious.MvvmCross.WindowsStore.Views.Suspension.MvxSuspensionManager.<SaveAsync>d__0.MoveNext()

我很确定我可以将异常根缩小到 WinRT API 调用的范围

Frame.GetNavigationState();

由 MvxSussuspension Manager 执行。当我直接调用此函数时,它将失败并出现相同的错误。

我知道 WinRT 帧导航堆栈只有在将非复杂类型用作导航参数时才能序列化。但是即使我只是在第一页上挂起,我的应用程序也会崩溃。

也许我使用 MvvmCross 暂停的方法错误,或者我错过了一些正确设置的步骤。

任何帮助都非常感谢!

挂起 Windows 应用商店应用:调用 MvxSuspensionManager.SaveAsync() 时出错

有两个问题正在禁用挂起管理器。正如您所说,MvX 使用复杂的 (ViewModelRequests) 对象而不是字符串进行导航。您可以通过创建自己的 ViewPresenter 来解决此问题,它应如下所示:

public class CustomViewPresenter : MvxStoreViewPresenter {
    //XXX: Holding a ref here because base class's ref to the frame is for some reason private.
    private Frame _curFrame;
    public CustomViewPresenter(Frame RootFrame) : base(RootFrame) {
        _curFrame = RootFrame;
    }
    public override void Show(MvxViewModelRequest request) {
        try {
            var requestTranslator = Mvx.Resolve<IMvxViewsContainer>();
            var viewType = requestTranslator.GetViewType(request.ViewModelType);
            var converter = Mvx.Resolve<IMvxNavigationSerializer>();
            var requestText = converter.Serializer.SerializeObject(request);
            _curFrame.Navigate(viewType, requestText);
        } catch (Exception exception) {
            MvxTrace.Trace("Error seen during navigation request to {0} - error {1}", request.ViewModelType.Name,
                           exception.ToString());
        }
    }
}

在您的基本页面对象(从 MvxStorePage 继承的对象)中,这将反序列化字符串化的 VMRequest。不要调用基本 onnavigatedto 方法:

    protected override void OnNavigatedTo(NavigationEventArgs e) {
        var reqData = (string)e.Parameter;
        var converter = Mvx.Resolve<IMvxNavigationSerializer>();
        var req = converter.Serializer.DeserializeObject<MvxViewModelRequest>(reqData);
        this.OnViewCreate(req, () => LoadStateBundle(e));
    }

一旦你完成了所有这些,你就有另一个问题。Mvx 将捆绑包序列化为 Dictionary*string, string*,而与 Mvx 捆绑在一起的暂停管理器只能处理 Dictionary*string, object*。您必须将Microsoft附带的标准暂停管理器复制并粘贴到您的应用中,并更改以下内容:

private readonly List<Type> _knownTypes = new List<Type>(); 

对此:

private readonly List<Type> _knownTypes = new List<Type>() { typeof(Dictionary<string, string>) };

然后,您需要通过将以下行添加到 setup.cs 文件中,将更改后的 Sussuspension Manager 提供给 MvX:

    protected override Cirrious.MvvmCross.WindowsStore.Views.Suspension.IMvxSuspensionManager CreateSuspensionManager() {
        return new MyFixedSuspensionManager();
    }

希望这一切都应该被纳入 Mvx 的未来版本之一,这样我们就不必做所有这些后空翻。

我猜这不是您使用中的错误 - 而是"标准"SuspensionManager的 MvvmCross 改编中的某个错误 - 可能在正在保存的对象类型中。

MvvmCross中的SuspensionManager代码主要基于Windows8.0 Common模板SuspensionManager - 但我记得在早期开发过程中(使用各种预览版本)有很多挫折,COMException经常返回诸如unknown error之类的无用消息。

实际上,Windows 8 暂停(到目前为止)在 MvvmCross 用户的优先级列表中并没有上升到很高的位置 - 所以如果当前改编需要添加或修复,我不会感到惊讶(特别是当 Windows 进入 8.1 时,LayoutAwarePage 已被弃用)。MvvmCross 中的加载/还原状态在许多应用程序中用于"内存中"缓存状态,但我个人没有使用它来从"挂起和关闭"终止状态恢复应用程序。

如果您的应用程序需要这种工作暂停功能并保存到/从磁盘保存,那么我相信只需稍加调试即可使MvxSuspensionManager和关联的MvxStorePage.SaveStateBundleMvxStorePage.LoadStateBundle代码工作,并且我相信重要方法都标记为virtual,以便可以轻松覆盖它们,但是......可悲的是。。。我相信让它们工作可能是一种令人沮丧的调试体验,包括来自COMException的"未知错误"时刻