Kotlin DSL と Navigation Compose における型安全性

組み込みの型安全な API を使用して、ナビゲーション グラフのコンパイル時の型安全性を実現できます。これらの API は、アプリで Navigation Compose または Navigation Kotlin DSL を使用している場合に使用できます。これらは Navigation 2.8.0 以降で使用できます。

これらの API は、XML を使用して構築されたナビゲーション グラフに Safe Args が提供するものと同等です。

ルートを定義する

Compose で型安全なルートを使用するには、まずルートを表すシリアル化可能なクラスまたはオブジェクトを定義する必要があります。

シリアル化可能なオブジェクトを定義するには、@Serializable アノテーションを Kotlin Serialization プラグインによって提供されるものを使用します。 このプラグインは、次の依存関係を 追加することでプロジェクトに追加できます。

ルートに使用するタイプを決定するには、次のルールを使用します。

  • オブジェクト: 引数のないルートにはオブジェクトを使用します。
  • クラス: 引数付きのルートにはクラスまたはデータクラスを使用します。
    1. KClass<T>: パラメータのないクラスや、すべてのパラメータにデフォルト値が設定されているクラスなど、引数を渡す必要がない場合に使用します。
    2. 例: 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> です。
  • デスティネーション タイプを定義することは、 route string のように composable("profile") を渡すよりも堅牢なアプローチです。
  • ルートクラスは、val id: String のように各ナビゲーション引数の型を定義するため、NavArgument は必要ありません。
  • プロファイル ルートの場合、toRoute() 拡張メソッドは Profile オブジェクトを NavBackStackEntry とその引数から再作成します。

グラフの設計方法について詳しくは、ナビゲーション グラフを 設計するをご覧ください。

ViewModel で引数にアクセスする

ViewModel の型安全なルートから引数にアクセスするには、 SavedStateHandle からルートを取得します。これを行うには、 SavedStateHandle.toRoute<T>() を呼び出します。ここで、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 を再構築し、そのプロパティを読み取ることで取得できます。

参考情報