循環型ナビゲーション

デスティネーションにポップバックする必要がある例としてわかりやすいのは、ナビゲーションが循環型の場合です。このドキュメントでは、そのようなユースケースの概要を示します。

シナリオ

アプリに A、B、C の 3 つのデスティネーションがあるとします。また、A から B、B から C、C から A に移動するアクションもあります。対応するナビゲーション グラフは次のようになります。

循環型ナビゲーションのデモ
図 1.3 つのデスティネーション(A、B、C)がある循環型ナビゲーションのグラフ

NavController は、ナビゲーション アクションごとに新しいデスティネーションをバックスタックに追加します。そのため、図のフローで移動を繰り返すと、バックスタックに各デスティネーションの複数のセット(A、B、C、A、B、C、A、B、C)が含まれることになります。

解決策

バックスタックでの繰り返しを回避するには、NavController.navigate() の呼び出しまたはナビゲーション アクションで、popUpTo()inclusive を指定します。

デスティネーション C に到達した後、バックスタックに各デスティネーション(A、B、C)のインスタンスが 1 つ含まれているとします。ユーザーをデスティネーション C からデスティネーション A に移動させるアクションまたは navigate() の呼び出しで、popUpTo()inclusive を指定するようにします。

この場合、ユーザーがデスティネーション C からデスティネーション A に戻ると、NavController も A にポップアップされます。つまり、スタックから B と C が削除されます。また、inclusive = true の場合、最初の A がポップされ、実質的にスタックがクリアされます。

Compose の実装

循環型の popUpTo() を Compose で解決する場合の実装は、次のとおりです。

// When creating your `NavGraph` in your `NavHost`.
composable("c") {
    DestinationC(
        onNavigateToA = {
          navController.navigate("a") {
            popUpTo("a") {
              inclusive = true
            }
          }
        },
    )
}

ビューの実装

循環型の popUpTo をビューで解決する場合の実装は、次のとおりです。

<fragment
    android:id="@+id/c"
    android:name="com.example.myapplication.C"
    android:label="fragment_c"
    tools:layout="@layout/fragment_c">

    <action
        android:id="@+id/action_c_to_a"
        app:destination="@id/a"
        app:popUpTo="@+id/a"
        app:popUpToInclusive="true"/>
</fragment>