您可以使用 NavEntryDecorator 類別,為目的地提供額外資訊或套用相同邏輯。這個類別會使用可組合函式,將返回堆疊中的每個 NavEntry 納入。換句話說,它會「裝飾」項目的內容。
建立自訂裝飾器
如要建立裝飾器,請擴充 NavEntryDecorator 類別,並覆寫下列方法:
decorate:可組合 lambda,會針對返回堆疊中的每個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 後,請透過下列其中一種方式裝飾返回堆疊中的項目:
- 使用
rememberDecoratedNavEntries。如果您有多個返回堆疊,且每個堆疊都有自己的修飾符組合,這個函式就非常實用 (詳情請參閱這份程式碼食譜)。這個函式會傳回NavEntry的裝飾清單,可與NavDisplay搭配使用。 - 使用
entryDecorators參數,直接將裝飾器提供給NavDisplay。NavDisplay會在幕後呼叫rememberDecoratedNavEntries,並顯示裝飾過的項目。
加入預設裝飾器
Navigation 3 包含名為 SaveableStateHolderNavEntryDecorator 的預設裝飾器,可讓 NavEntry 的狀態在設定變更和程序終止後仍能保留。它會使用 SaveableStateProvider 包裝 NavEntry 內容,讓 NavEntry 內容中的 rememberSaveable 呼叫正常運作。
除非裝飾器提供 SaveableStateProvider,否則請在提供的裝飾器清單中,將 SaveableStateHolderNavEntryDecorator 做為第一個裝飾器。這個物件是使用 rememberSaveableStateHolderNavEntryDecorator 建立。
例如:
// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator NavDisplay( entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), remember { CustomNavEntryDecorator() } ), // ... )
使用 ResultEventBusNavEntryDecorator 傳遞結果
自 Navigation 3 1.2.0 起,您可以使用 ResultEventBusNavEntryDecorator,透過 LocalResultEventBus 組合本機為每個 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。
請勿使用裝飾器執行下列操作:
- 將依附元件傳遞至單一
NavEntry。 - 提供範圍比返回堆疊更廣的依附元件。
在這兩種情況下,請改為在建立 NavEntry 時直接傳遞依附元件。
如需更多程式碼範例,請參閱 NavEntryDecorator。