使用 NavGraph 替换目的地(使用 app:popUpTo 时的事务)

Cos*_* SD 5 android android-navigation android-jetpack android-architecture-navigation

我们需要实现一个状态机驱动的导航,其中当前显示的屏幕取决于当前状态。因此,到目前为止,我们的方法是使用全局操作并在状态发生变化时导航到正确的屏幕。乍一看,一切似乎都很好,但是,当app:popUpTo在动作上使用属性时,我们开始注意到一些奇怪的行为。

在我们的具体案例中,我们有 2 个子导航图(让我们称它们为NG1NG2),其中NG2是状态机驱动的。假设我们在 screen AinNG1然后我们导航到NG2,它添加了 screen B。我们现在有两个选择:

  1. 如果我们使用 with (有效地旨在替换with )的操作导航到 screen C(in NG2) ,那么有时,Fragment 会短暂启动 ( ) 几十毫秒,然后在开始之前停止。因此,我们得到。带有 , 的操作似乎不是事务性的。app:popUpTo="@+id/NG2"BCAonStartCB -> CB -> A -> CpopUpTo
  2. 如果我们使用不带 的操作导航到 screen C(in NG2) app:popUpTo="@+id/NG2",则 screenA不会启动,而是B留在后堆栈中。因此,如果 screenB需要再次显示,我们最终会得到一个看起来像 的 backstack A / B / C / B,这不是我们的目标。

当然,我们正在寻找的行为是在 1 中尝试的行为,我们可以从一个屏幕移动X到一个屏幕Y再到一个屏幕Z,带有 popping Y,但不是简单地开始X。是不是我们做错了什么或者是android-navigation组件中的错误?


我还添加了一些日志,显示我刚刚复制的实际日志(时间戳是实际的):

// Here we navigate from A to B
2020-03-09 19:14:14.999 BaseAppNavigator: Navigating to directions: com.example.app:id/toNavGraph2
2020-03-09 19:14:15.006 BaseAppNavigator.OnDestinationChangedListener: Navigation destination changed: com.example.app:id/fragmentB
2020-03-09 19:14:15.007 BaseAppNavigator.OnDestinationChangedListener: Active navigation graph changed to: com.example.app:id/navGraph2
2020-03-09 19:14:15.235 BaseViewModelFragment: OnStart: FragmentB
2020-03-09 19:14:15.247 BaseViewModelFragment: OnStop: FragmentA

// Here we trigger navigate from B to C, with a destination with popUpTo="navGraph2"
2020-03-09 19:14:56.422 BaseAppNavigator: Navigating to directions: com.example.app:id/toFragmentC
2020-03-09 19:14:56.430 BaseAppNavigator.OnDestinationChangedListener: Navigation destination changed: com.example.app:id/fragmentC
2020-03-09 19:14:56.516 BaseViewModelFragment: OnStart: FragmentA
2020-03-09 19:14:56.529 BaseViewModelFragment: OnStop: FragmentB
2020-03-09 19:14:56.537 BaseViewModelFragment: OnDestroy: FragmentB
2020-03-09 19:14:56.580 BaseViewModelFragment: OnStart: FragmentC
2020-03-09 19:14:56.613 BaseViewModelFragment: OnStop: FragmentA

Run Code Online (Sandbox Code Playgroud)

执行以下操作:

<action
      android:id="@+id/toFragmentC"
      app:destination="@id/fragmentC"
      app:popUpTo="@+id/NavGraph2" />
Run Code Online (Sandbox Code Playgroud)