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 字符串相比,定义目的地类型是一种更可靠的方法。
  • 路线类定义了每个导航实参的类型(如 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> 目的地。任何导航实参(例如 id)都可以通过使用 NavBackStackEntry.toRoute 重建 Profile 并读取其属性来获取。

其他资源