popUpTo似乎在导航组件中不起作用

时间:2020-01-22 09:44:12

标签: android android-fragments android-navigation

所以我正在使用android导航组件,但遇到了问题(2.2.0-rc04版本)。

我有一个welcomeFragment(wF)。我想从wF导航到另一导航图中的loginSellerFragment(lSF)。我也不想在导航到wF时从堆栈(popUpTo,popUpToInclusive)中删除lSF,因为用户可能想返回到它。

<fragment
    android:id="@+id/welcomeFragment">
    <action
        android:id="@+id/action_welcomeFragment_to_nav_onboarding_seller"
        app:launchSingleTop="true"
        app:destination="@id/nav_onboarding_seller" />
</fragment>

导航到lSF后,堆栈看起来像这样: wF lSF

我们现在在lSF上,登录后我们想转到feedFragment(fF),它又在单独的图中,但是这次我们要清除所有的后退堆栈,因为如果用户登录并按回,他希望应用程序退出,而不是让他回到wFlSF,因此我在popUpTo="@id/loginSellerFragment popUpToInclusive='true"的操作中使用了lSFfF

<fragment
    android:id="@+id/loginSellerFragment">
    <action
        android:id="@+id/action_login_to_seller"
        app:destination="@+id/seller" . //this is the graph that has as firstDestination, feedFragment
        app:launchSingleTop="true"
        app:popUpTo="@id/loginSellerFragment"
        app:popUpToInclusive="true" />
</fragment>

因此,此时在后退堆栈中的值应该仅为 fF ,因为我们删除了lSF(包括lSF在内的所有内容)

问题

当我在fF上并按回去时,该应用程序不会关闭,而是将我带到wFwF应该已经从后堆栈中弹出了)< / p>

我尝试过的事情

我尝试使用popUpTo="@id/loginSellerFragment popUpToInclusive='true"来代替popUpTo="@id/welcomeFragment popUpToInclusive='true",但效果很好,但是我很确定这不是应该这样做的方法。我在这里想念什么?我在构建堆栈时错了吗?

我也尝试从popUpTo="@id/welcomeFragment popUpToInclusive='true"导航到wF后添加lSF,但这会破坏我的用户体验,因为我不希望应用程序在我退出时退出m仍在登录过程中。

请注意,所有这些片段都在单独的图中。 要导航,我使用FragmentDirections例如:findNavController.navigate(WelcomeFramgentDirections.actionXtoY())

2 个答案:

答案 0 :(得分:8)

在使用popUpTo选项时,要掌握导航组件如何操纵后退堆栈并不容易。

您在问题中提到的解决方案是正确的: 您确实应该使用popUpTo="@id/welcomeFragment" popUpToInclusive="true"而不是popUpTo="@id/loginSellerFragment" popUpToInclusive="true"

我将尝试解释原因。

  • 启动应用程序时,堆栈将为空,并显示welcomeFragment

  • welcomeFragment导航到loginSellerFragment时,您的后栈中将有welcomeFragment

  • 与登录相比,您将从loginSellerFragment导航到feedFragment,在后退堆栈中,您将拥有loginSellerFragmentwelcomeFragment

自从您使用popUpTo="@id/welcomeFragment"以来,应用程序就会开始从后退栈中弹出(删除)片段,直到达到welcomeFragment。由于我们使用了welcomeFragment,因此popUpToInclusive="true"也将被删除。

Backstack的行为应类似于FIFO(先进先出)堆栈,因此,如果要以这种方式删除片段,则:

首先将删除顶部的片段,即loginSellerFragment

接下来,welcomeFragment将是最上面的片段。由于我们需要弹出片段,直到到达welcomeFragment,这才是我们停止的地方,但是welcomeFragment也将由于popUpToInclusive="true"而被删除,并且您的后退栈将为空。

如果您尝试从welcomeFragment向后导航,则由于后栈为空,因此将退出应用程序。

我希望这会有所帮助。您还可以阅读有关堆栈数据结构的更多信息。

答案 1 :(得分:0)

对我来说设置 XML 代码并没有真正解决问题,不得不使用额外的代码行

  findNavController()
                .navigate(R.id.navigationFragment,
                    null,
                    NavOptions.Builder()
                        .setPopUpTo(R.id.splashFragment,
                            true).build()
                )