在导航表单选项菜单项时导航到嵌套图时如何返回用户离开的位置?

How to get back where user left off when navigated to a nested graph when navigated form option menu item?

我有一个需要多个配对设备的应用程序。从应用程序的流程来看,有多个地方可以初始化配对流程。

所以我将配对流作为嵌套图,在 根图 中,我有一个全局操作 pairing_action。在嵌套图中,我有另一个全局操作 finish_pairing.

问题是,当我从配对片段调用 finish_pairing 操作时,无论我从哪里启动配对流程,我总是会在主屏幕上结束。

但这不是我想要的,我想返回到我从启动配对流程的屏幕(进入配对流程时我离开的地方)。

代码如下。

navigation.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/navigation"
    app:startDestination="@id/start_fragment">

    <!-- Global action to start pairing -->
    <action android:id="@+id/pairing_action"
        app:destination="@id/pairing"/>

    <fragment ... />
    <fragment ... />
    <fragment ... />

    <!-- Nested pairing flow -->
    <navigation android:id="@+id/pairing"
        android:label="Pairing"
        app:startDestination="@id/pairing_fragment">

        <!-- Nested global action to finish pairing -->
        <!-- Should get to the fragment which initiated pairing! -->
        <action android:id="@+id/finish_pairing"
            app:popUpTo="@id/pairing"
            app:popUpToInclusive="true" />

        <fragment ... />
        <fragment ... />
        <fragment ... />
    </navigation>
</navigation>

嵌套配对导航图

编辑 1:

即使我在配对流程中按下后退按钮,我也会返回主屏幕。

示例:我进入配对屏幕是这样的:

main -> devices -> pairing -> enter code

现在,当我从 enter code 屏幕调用 finish_pairing 全局操作时(或按返回键 2 次),我想 return 返回到 devices 屏幕。但我最终选择了 main

编辑 2:

这是从 devices 屏幕转到 pairing graph 时的 logcat:

V/FragmentManager: Commit: BackStackEntry...
D/FragmentManager: mName=2-2131231057 mIndex=-1 mCommitted=false
...
D/FragmentManager: Operations:
D/FragmentManager: Op #0: REPLACE PairingFragment...
...
D/FragmentManager: Op #1: SET_PRIMARY_NAV PairingFragment...
...
V/FragmentManager: Run: BackStackEntry...
V/FragmentManager: Bump nesting in BackStackEntry... by -1
V/FragmentManager: Bump nesting of StartFragment... to 1
V/FragmentManager: Bump nesting of StartFragment... to 0
V/FragmentManager: Bump nesting of DevicesFragment... to 1
V/FragmentManager: Bump nesting of DevicesFragment... to 0
V/FragmentManager: remove: DevicesFragment... nesting=0

V/FragmentManager: add: StartFragment...
V/FragmentManager: Bump nesting in BackStackEntry... by 1
V/FragmentManager: Bump nesting of StartFragment... to 1
V/FragmentManager: Bump nesting of StartFragment... to 2
V/FragmentManager: Bump nesting of PairingFragment... to 1
V/FragmentManager: Bump nesting of PairingFragment... to 2
V/FragmentManager: remove: StartFragment... nesting=2

V/FragmentManager: add: PairingFragment...
V/FragmentManager: Added fragment to active set PairingFragment...
V/FragmentManager: moveto CREATED: PairingFragment...
V/FragmentManager: moveto ACTIVITY_CREATED: PairingFragment...
V/FragmentManager: moveto STARTED: PairingFragment...
V/FragmentManager: moveto RESUMED: PairingFragment...

V/FragmentManager: movefrom RESUMED: DevicesFragment...
V/FragmentManager: movefrom STARTED: DevicesFragment...
V/FragmentManager: movefrom ACTIVITY_CREATED: DevicesFragment...
W/FragmentManager: moveToState: Fragment state for DevicesFragment... not updated inline; expected state 1 found 2
V/FragmentManager: movefrom CREATED: DevicesFragment...
D/FragmentManager: Clearing non-config state for DevicesFragment...
D/FragmentManager: onCleared called for FragmentManagerViewModel{a60610c} Fragments () Child Non Config () ViewModelStores ()
V/FragmentManager: Removed fragment from active set DevicesFragment...

似乎在导航到 pairing graph 时弹出了后台堆栈(首先是 devices 屏幕,然后是 start 屏幕),然后转到 pairing 屏幕。

这不是一个错误吗? global action 为什么要pop backstack?!

我正在使用选项菜单项进入配对流程。

只需从嵌套图创建一个常规 action 并设置 popUpTo 嵌套图本身。

<action
    android:id="@+id/action_pairing_nav_graph_self"
    app:popUpTo="@+id/pairing_nav_graph" />

设计

XML

<navigation...
    android:id="@+id/nav_graph.xml"
    app:startDestination="@id/fragmentMain">

    <fragment...>
        <action.../>
        <action.../>
        <action.../>
    </fragment>
    <fragment...>
        <action.../>
    </fragment>
    <fragment...>
        <action.../>
    </fragment>

    <!-- nested graph -->
    <navigation
        android:id="@+id/pairing_nav_graph"
        ...>
        <fragment ...>
        <fragment...>
            <action.../>
        </fragment>

        <!-- action to the graph itself -->
        <action
            android:id="@+id/action_pairing_nav_graph_self"
            app:popUpTo="@+id/pairing_nav_graph"
         />
    </navigation>
</navigation>

Checkout: device-pairing branch in repo 一个工作示例。

我在我的应用程序中大量使用菜单导航。 NavigationUI supports it. But if you read the documentation 小心一点,有一点备注:

By default, the back stack will be popped back to the navigation graph's start destination. Menu items that have android:menuCategory="secondary" will not pop the back stack.

这就是为什么从设备屏幕 "broke" 返回堆栈进入配对屏幕的原因。

所以解决方案是将 android:menuCategory="secondary" 添加到设备屏幕上的菜单,它开始按预期工作。