Kotlin DSL 和 Navigation Compose 中的類型安全

您可以使用內建的類型安全 API,為導覽圖提供編譯時間類型安全。如果應用程式使用 Navigation ComposeNavigation Kotlin DSL,即可使用這些 API。這些功能已於 Navigation 2.8.0推出。

這些 API 等同於 Safe Args 提供給使用 XML 建構的導覽圖。

定義路徑

如要在 Compose 中使用型別安全的路徑,您必須先定義可序列化的類別或物件,代表您的路徑。

如要定義可序列化的物件,請使用 Kotlin 序列化外掛程式提供的 @Serializable 註解。如要將這個外掛程式新增至專案,請新增這些依附元件

請根據下列規則,決定路線要使用的類型:

  • 物件:使用物件做為不含引數的路徑。
  • 類別:針對含有引數的路徑使用類別或資料類別。
  • KClass<T>:如果不需要傳遞引數,例如沒有參數的類別,或是所有參數都有預設值的類別,請使用這個函式。
    1. 例如:Profile::class

在所有情況下,物件或類別都必須可序列化。

例如:

// Define a home route that doesn't take any arguments
@Serializable
object Home

// Define a profile route that takes an ID
@Serializable
data class Profile(val id: String)

建立圖表

接著,您需要定義導覽圖。使用 composable() 函式,將可組合函式定義為導覽圖中的目的地。

NavHost(navController, startDestination = Home) {
     composable<Home> {
         HomeScreen(onNavigateToProfile = { id ->
             navController.navigate(Profile(id))
         })
     }
     composable<Profile> { backStackEntry ->
         val profile: Profile = backStackEntry.toRoute()
         ProfileScreen(profile.id)
     }
}

請注意以下範例中的事項:

  • composable() 會使用型別參數。也就是 composable<Profile>
  • composable("profile") 做法相比,定義目的地類型是更穩健的方法,因為這樣做不需要傳遞 route string
  • 路徑類別會定義每個導覽引數的型別,如 val id: String 所示,因此不需要 NavArgument
  • 針對設定檔路徑,toRoute() 擴充方法會從 NavBackStackEntry 及其引數重新建立 Profile 物件。

如要進一步瞭解如何設計圖表,請參閱「設計導覽圖」頁面。

在 ViewModel 中存取引數

如要在 ViewModel 中存取類型安全路徑的引數,可以呼叫 SavedStateHandle.toRoute<T>(),從 SavedStateHandle 擷取路徑,其中 T 是路徑類別:

class ProfileViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {
    private val profile = savedStateHandle.toRoute<Profile>()
    private val userInfo: Flow<UserInfo> = userInfoRepository.getUserInfo(profile.id)
}

最後,您可以傳遞路徑的例項,使用 navigate() 函式前往可組合項:

navController.navigate(Profile(id = 123))

這會將使用者導覽至導覽圖中的 composable<Profile> 目的地。您可以重建 Profile (使用 NavBackStackEntry.toRoute) 並讀取其屬性,取得任何導覽引數 (例如 id)。

其他資源