NavEntryDecorator クラスを使用すると、追加情報を提供したり、同じロジックをデスティネーションに適用したりできます。このクラスは、バックスタック内の各 NavEntry をコンポーズ可能な関数でラップします。つまり、エントリのコンテンツを装飾します。
カスタム デコレータを作成する
デコレータを作成するには、NavEntryDecorator クラスを拡張し、次のメソッドをオーバーライドします。
decorate- バックスタック内のNavEntryごとに呼び出されるコンポーザブル ラムダ。NavEntryをパラメータとして受け取ります。これにより、エントリのcontentKeyをキーとする状態オブジェクトを作成できます。CompositionLocalProviderを使用して、エントリのコンテンツに依存関係を提供できます。また、コンテンツをコンポーズ可能な関数で囲んだり、副作用をトリガーしたりすることもできます。このメソッド内では、常にentry.Content()を呼び出す必要があります。onPop-NavEntryがバックスタックから削除され、コンポジションから離れたときに呼び出されるコールバック。削除されたエントリのcontentKeyを受け取ります。contentKeyを使用して、そのエントリに関連付けられている状態を特定してクリーンアップします。
次の例では、NavEntryDecorator クラスを拡張してカスタム デコレータを作成しています。
// import androidx.navigation3.runtime.NavEntryDecorator class CustomNavEntryDecorator<T : Any> : NavEntryDecorator<T>( decorate = { entry -> Log.d("CustomNavEntryDecorator", "entry with ${entry.contentKey} entered composition and was decorated") entry.Content() }, onPop = { contentKey -> Log.d("CustomNavEntryDecorator", "entry with $contentKey was popped") } )
デコレータが状態にアクセスする必要がある場合は、その状態を作成するコンポーズ可能な関数を作成し、それを使用してデコレータを構築します。実装例については、rememberSaveableStateHolderNavEntryDecorator のソースコードをご覧ください。これにより、状態(SaveableStateHolder)が作成され、デコレータの作成に使用されます。
バックスタックを装飾する
NavEntryDecorator を作成したら、次の 2 つの方法のいずれかでバックスタックのエントリを装飾します。
rememberDecoratedNavEntriesを使用します。この関数は、複数のバックスタックがあり、それぞれに独自のデコレータ セットがある場合に便利です(詳細については、こちらのコードレシピをご覧ください)。この関数は、NavDisplayで使用できるNavEntryのデコレートされたリストを返します。entryDecoratorsパラメータを使用して、デコレータをNavDisplayに直接指定します。NavDisplayは内部でrememberDecoratedNavEntriesを呼び出し、装飾されたエントリを表示します。
デフォルトのデコレータを含める
Navigation 3 には、SaveableStateHolderNavEntryDecorator という名前のデフォルトのデコレータが含まれています。これにより、構成の変更やプロセスの終了後も NavEntry の状態を保持できます。NavEntry コンテンツを SaveableStateProvider でラップします。これにより、NavEntry コンテンツ内の rememberSaveable 呼び出しが正しく機能するようになります。
デコレータが SaveableStateProvider を提供していない限り、提供されたデコレータのリストの最初のデコレータとして SaveableStateHolderNavEntryDecorator を含める必要があります。rememberSaveableStateHolderNavEntryDecorator を使用して作成されます。
次に例を示します。
// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator NavDisplay( entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), remember { CustomNavEntryDecorator() } ), // ... )
ResultEventBusNavEntryDecorator を使用して結果を渡す
Navigation 3 1.2.0 以降では、LocalResultEventBus コンポジション ローカルを使用して、ResultEventBusNavEntryDecorator で各 NavEntry に ResultEventBus を提供できます。
デフォルトでは、rememberResultEventBusNavEntryDecorator は rememberResultEventBus を使用して、独自の ResultEventBus インスタンスを内部で作成して記憶します。デコレータ階層の外(最上位のアプリ スキャフォールディングなど)でイベントバスにアクセスする必要がある場合は、rememberResultEventBus を呼び出して rememberResultEventBusNavEntryDecorator(resultEventBus) に渡すことで、ResultEventBus をホイスティングできます。
val resultEventBus = rememberResultEventBus() NavDisplay( /* ... */ entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus) ) )
結果の送信とモニタリングの詳細については、結果を返すをご覧ください。
デコレータを使用するタイミング
デコレータを使用すると、次のことができます。
- バックスタック内の
NavEntryごとに依存関係を作成します。たとえば、ViewModelStoreNavEntryDecoratorはNavEntryごとにViewModelStoreを作成します。 - デスティネーション間で結果を渡し、通信します。たとえば、
ResultEventBusNavEntryDecoratorは、バックスタック内のデスティネーションにResultEventBusを提供します。 - オブジェクトのスコープを複数の
NavEntryに設定します。たとえば、複数のエントリ間でViewModelを共有する場合です。 - 複数の
NavEntryに対して同じ操作を行います。たとえば、各エントリのロギング、デバッグ、トレース オペレーションを実行します。 - 同じコンポーズ可能な関数で
NavEntryをラップする。 NavEntryに関連付けられた状態をクリーンアップします。たとえば、エントリがバックスタックから削除されると、ViewModelStoreNavEntryDecoratorは関連付けられたViewModelStoreをクリアします。
デコレータは、次の目的で使用しないでください。
- 依存関係を 1 つの
NavEntryに渡します。 - バックスタックよりもスコープが広い依存関係を提供する。
どちらの場合も、代わりに NavEntry の作成時に依存関係を直接渡します。
その他のコード例については、NavEntryDecorator をご覧ください。