對目的地套用邏輯或包裝函式

您可以使用 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 參數,直接將裝飾器提供給 NavDisplayNavDisplay 呼叫 rememberDecoratedNavEntries,並顯示裝飾項目。

加入預設裝飾器

Navigation 3 包含名為 SaveableStateHolderNavEntryDecorator 的預設裝飾器,可讓 NavEntry 的狀態在設定變更和程序終止後仍維持不變。它會使用 SaveableStateProvider 包裝 NavEntry 內容,讓 NavEntry 內容內的 rememberSaveable 呼叫正常運作。

除非裝飾器提供 SaveableStateProvider,否則您應在提供的裝飾器清單中,將 SaveableStateHolderNavEntryDecorator 做為第一個裝飾器。這是使用 rememberSaveableStateHolderNavEntryDecorator 建立的。

例如:

// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
NavDisplay(
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        remember { CustomNavEntryDecorator() }
    ),
    // ...
)

使用裝飾器

修飾符的用途如下:

  • 為返回堆疊中的每個 NavEntry 建立依附元件。舉例來說,ViewModelStoreNavEntryDecorator 會為每個 NavEntry 建立 ViewModelStore
  • 將物件範圍設為多個 NavEntry。舉例來說,在多個項目之間共用 ViewModel
  • 對多個 NavEntry 執行相同動作。舉例來說,針對每個項目執行記錄、偵錯或追蹤作業。
  • 使用相同的可組合函式包裝 NavEntry
  • 清除與 NavEntry 相關聯的狀態。舉例來說,當項目從返回堆疊中移除時,ViewModelStoreNavEntryDecorator 會清除相關聯的 ViewModelStore

請勿使用裝飾器執行下列操作:

  • 將依附元件傳遞至單一 NavEntry
  • 提供範圍比返回堆疊更廣的依附元件。

在這兩種情況下,請在建立 NavEntry 時直接傳遞依附元件。

如需更多程式碼範例,請參閱 NavEntryDecorator