用MvvmCross处理取消CancellationToken激活的ViewModel销毁的最佳方法是什么?

时间:2018-08-14 20:31:02

标签: xamarin cross-platform mvvmcross viewmodel

我有一个MvvmCross ViewModel,它调用了DataService的不同异步方法。 类似于以下内容:

public class LoginViewModel : MvxViewModel
{
    private readonly IIdentityService _dataService;
    private CancellationTokenSource _viewModelCancellationTokenSource;
    public IMvxCommand GoLogin { get; set; }

    public LoginViewModel(IIdentityService identityService)
    {
        _dataService = identityService;
        _viewModelCancellationTokenSource = new CancellationTokenSource();

        GoLogin = new MvxCommand(async () => await ProcessLogin());
    }

    private async Task ProcessLogin()
    {
        // calling the dataservice which must stop processing
        // (to cancel) in case if the ViewModel is being destroyed
        await _dataService.AssureIsLoggedIn(data, _viewModelCancellationTokenSource.Token);
        await NavigationService.Navigate<LoginNextStepViewModel>();
    }

    public override void ViewDestroy(bool viewFinishing = true)
    {
        base.ViewDestroy(viewFinishing);

        // not sure if that is a right (and working) place
        _viewModelCancellationTokenSource.Cancel();
    }
}

因此,MvvmCross尚不清楚ViewModel销毁的部分。它描述了Construction, Init, Reload and Start,但没有对destroying做出任何明确的定义:

  

跨多个监视其他View / ViewModel生命周期事件   平台非常棘手,特别是一旦开发人员开始   在“基本”展示模型之外进行实验并开始使用   标签,拆分视图,弹出窗口,弹出窗口等

     

对于大多数视图模型,通常不尝试监视其他生命周期   事件。可以,因为大多数视图模型不执行任何操作,并且   当视图不存在时,不会消耗任何资源-因此这些   可以只在系统需要   记忆回来。

但是,除了自定义平台情况以外,还有许多情况,例如从视图模型导航回去,或者(随后)在关闭视图后再次导航到当前视图模型。

那么,处理它的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

根据您的代码:

// calling the dataservice which must stop processing
// (to cancel) in case if the ViewModel is being destroyed

在异步方法完成执行之前,不会破坏ViewModel。我认为您将View与ViewModel混淆了。

对于登录页面,通常会阻止用户离开它,直到服务器调用通过为止。

如果出于某种原因要取消,则需要确定要处理的方案,没有一个通用的地方。您的选择是视图回调:

void ViewDisappearing();
void ViewDisappeared();  
void ViewDestroy();

和导航事件:

event BeforeNavigateEventHandler BeforeNavigate;
event AfterNavigateEventHandler AfterNavigate;
event BeforeCloseEventHandler BeforeClose;
event AfterCloseEventHandler AfterClose;
event BeforeChangePresentationEventHandler BeforeChangePresentation;
event AfterChangePresentationEventHandler AfterChangePresentation;