ViewModelで画面引数を受け取る

Kenji Abe
Dec 30, 2022
Photo by Zoya Loonohod on Unsplash

意外と知られていない気がするので、ViewModelで画面引数を受け取る方法をまとめておきます。

AssistedInjectなどの特殊なことも必要なく、かなり簡単にViewModelで画面引数を受け取れます。

受け取る方法

実はViewModelで画面引数を受け取るには非常に簡単で、以下のように SavedStateHandle から取得できます。

class SampleViewModel(
savedStateHandle: SavedStateHandle
) : ViewModel() {

val userId: String? = savedStateHandle["userId"]

// ...
}

ViewModelのコンストラクタで SavedStateHandle を受け取るようにしておくと、画面引数として渡したときと同じキーを使うだけ取得できます。

渡す方法

画面引数を渡す方法に特別なことは不要で、ActivityのIntent、Navigation Component、Navigation Compose、どの渡し方でも SavedStateHandle で取得することができます。

// Activity Intent
val intent = Intent(this, SampleActivity::class.java).apply {
putExtra("userId", "xxxx")
}
startActivity(intent)


// Navigation Component
val action = SampleFragmentDirections.action("xxxx")
findNavController().navigate(action)


// Navigation Compose
NavHost(navController = navController, startDestination = "start") {
composable("start") {
HomeScreen(
onClick = { navController.navigate("sample/xxxx") }
)
}
composable("sample/{userId}") {
// ...
}
}

Safe Args対応

Navigation Componentを使ってるときにSafe Argsを使うことが多いと思いますが、SavedStateHandle から引数を取得するときにもSafe Argsのクラスに変換することが可能です。 fromSavedStateHandle というヘルパーメソッドが生成されるので、それを使うだけで簡単に対応することができます。

class SampleViewModel(
savedStateHandle: SavedStateHandle
) : ViewModel() {

val args = SampleFragmentArgs.fromSavedStateHandle(savedStateHandle)

// ...
}

Navigation ComposeのType Safe対応

Navigation Composeを使ってる場合は自分でWrapperを実装する感じになります。詳細は以下の公式ドキュメントにまとまっています。実装自体は単純です。

--

--

Kenji Abe

Programmer / Gamer / Google Developers Expert for Android, Kotlin / @STAR_ZERO