MVVMCross ViewModel构造失败通知

时间:2014-06-06 16:46:50

标签: mvvmcross

我们已经注意到,在我们的移动应用程序中,用户已经多次报告应用程序挂起或看起来在视图之间无法响应/在视图之间切换时很少发生崩溃。我们已经将这些情况跟踪到我们的视图模型构造函数抛出未捕获的异常时。

我们希望提供一个解决方案,以便如果视图模型由于某种原因而无法构建,那么我们可以通知用户并提供一些消息,这些消息在我们通过支持进行记录时对我们有用。

我一直在考虑这样做,但还没有找到一种可靠的方法来实现这一目标。

我们尝试的第一件事是IMvxViewModelLocator级别。我们已经有IMvxViewModelLocator的自定义实现,所以我们对此进行了修改。我们允许抛出所有异常,然后我们有一个IErrorHandler接口,每个平台都实现。然后我们调用它来尝试显示一个对话框。事实证明这是不可靠的,并且对话框并不总是显示出来。类似的东西:(注意 - 这里ResolveViewModel将始终返回true或throw)

    public override bool TryLoad(Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState, out IMvxViewModel viewModel)
    {
        try
        {
            return ResolveViewModel(viewModelType, parameterValues, savedState, out viewModel);
        }
        catch (Exception exception)
        {
            _errorHandler.HandleViewModelConstructionException(viewModelType, exception);
            viewModel = null;
            return false;
        }
    }

我们理想的做法是拦截构建视图模型然后重新请求ErrorViewModel的任何失败。我们尝试过两种方式:

1) 我们已经尝试为每个平台定义一个自定义IMvxViewDispatcher,我们试图拦截失败,如下所示,但如果构造函数中的异常被抛出,我们永远不会回到这一步:

public class TouchDispatcher : MvxTouchUIThreadDispatcher, IMvxViewDispatcher
{
    private readonly IMvxTouchViewPresenter _presenter;

    public TouchDispatcher(IMvxTouchViewPresenter presenter)
    {
        _presenter = presenter;
    }

    public bool ShowViewModel(MvxViewModelRequest request)
    {
        Action action = () =>
            {
                _presenter.Show(request);
            };
        try
        {
            bool success = RequestMainThreadAction(action);
            return !success ? HandleError() : success;
        }
        catch (Exception)
        {
            return HandleError();
        }
    }
    // Other bits
}

2) 我们认为我们可能会在演示者层面取得更大的成功。我们为每个平台修改了ViewPresenter,并覆盖了void Show(MvxViewModelRequest request)。事实证明这并不成功,因为例外情况不会传播到目前为止。

这让我想到也许我们最好再次在IMvxViewModelLocator级尝试这个。

有没有人找到一种方法来可靠地拦截失败以构建视图模型,然后理想地重新请求不同的视图模型/向用户呈现一些对话框?

1 个答案:

答案 0 :(得分:0)

您似乎已经确定问题的核心是:"查看模型构造函数会抛出未捕获的异常。"

由于ViewModel通常是在ViewDidLoadOnCreateNavigatedTo之类的View生命周期覆盖期间构建的,因此这会有点问题 - 这通常在Presenter之后完成请求演示。

由于您已经找到了一个方便的地方来确定ViewModel构建失败的时间是自定义IMvxViewModelLocator - 其他类似IMvxViewModelLoader也是可能的。这可能是捕获错误并触发错误处理的最简单的地方 - 然后您可以在那里获取IMvxViewDispatcher(或演示者)以更改显示。但是,您仍需要确保您的视图可以处理null创建的ViewModel - 因为ViewDidLoad等调用仍需要完成。