导航后清除整个后堆栈

时间:2019-12-23 13:33:56

标签: mvvmcross

导航到特定ViewModel之后,是否可以清除整个导航堆栈(包括ViewModel和View)?在这种情况下,我需要在用户注销时破坏导航堆栈。据我了解,MvxPopToRootPresentationHint仅在LoginViewModel首先位于导航堆栈的根处时才有帮助。

我还应该提到,我在Android上的堆栈既包含活动又包含片段,并且我最终需要导航至片段(因此,在CLEAR_TOP中使用意图很难)

InterstitialContainerViewModel (NoHistory = true on Activity)
InterstitialViewModel
      ↓
LoginContainerViewModel (NoHistory = true on Activity)
LoginViewModel
      ↓
MainContainerViewModel
MainViewModel && MenuViewModel
                       ↓
                   LogoutAsync
                       ↓
Should give me a new instance of LoginContainerViewModel/LoginViewModel 
with no other ViewModels, Activities, or Fragments in the stack

理想情况下,我想在共享代码中独立于平台执行此操作,但是如果要实现此流程,则需要自定义演示者代码,这是可以的。

1 个答案:

答案 0 :(得分:1)

这可能不是实现此目的的最干净的方法,但似乎可行:

1。创建一个MvxPresentationHint(使用共享代码)

public class LogoutPresentationHint : MvxPresentationHint
{
}

2。创建具有ChangePresentation 覆盖的自定义演示者:

internal class MyPresenter : MvxAppCompatViewPresenter
{
    public MyPresenter(IEnumerable<Assembly> androidViewAssemblies)
        : base(androidViewAssemblies)
    {
    }

    public override Task<bool> ChangePresentation(MvxPresentationHint hint)
    {
        if (hint is LogoutPresentationHint)
        {
            var intent = new Intent(CurrentActivity, typeof(LoginContainerActivity));
            intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.NewTask);
            ShowIntent(intent, new Bundle());
            CurrentActivity.Finish();
            Show(new MvxViewModelRequest(typeof(LoginViewModel)));
        }

        return base.ChangePresentation(hint);
    }
}

3。在Setup.cs 中使用自定义演示者:

protected override IMvxAndroidViewPresenter CreateViewPresenter()
    => new MyPresenter(AndroidViewAssemblies);

4。覆盖OnBackPressed中的LoginContainerActivity,以在用户按下时最小化应用程序

public override void OnBackPressed()
{
    Minimise();
}

private void Minimise
{
    var minimiseIntent = new Intent(Intent.ActionMain);
    minimiseIntent.AddCategory(Intent.CategoryHome);
    minimiseIntent.SetFlags(ActivityFlags.NewTask);
    StartActivity(minimiseIntent);
}

5。在MvxPresentationHint 中使用新的LogoutAsync导航:

private async Task LogoutAsync()
    => await NavigationService.ChangePresentation(new LogoutPresentationHint());

这几乎完美。删除了整个后堆栈,并正确创建了一个新的登录ViewModels和Activity / Fragments实例。我发现的唯一警告是,如果用户回退(这会最小化该应用程序),然后从最近的状态重新打开该应用程序,则它会重新打开到没有碎片的容器活动中。演示者中仅引发ActivityLifetimeListener_ActivityChanged方法。可能可以使用该方法并在此时正确显示片段,但我还没有设法正确解决这个问题。