🏃♂️
Android | Compose でディープリンクを実装するときはクエリパラメータにデフォルト値を設定しよう
はじめに
Compose を使ったアプリを開発していて以下のエラーでハマったので備忘録です。
java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/login } cannot be found in the navigation graph NavGraph(0x0) startDestination={Destination(0xa268bffc) route=login}
何が起こったのか
ナビゲーションを使って login
ルート(ログイン画面)に遷移させようとしたとき、上記のエラーが発生してしまいました。login
へのルートは以下のように定義していました。
NavHost(startDestination = "login") {
loginNavGraph()
homeNavGraph()
...
}
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.loginNavGraph() {
composable(
route = "login",
deepLinks = listOf(navDeepLink { uriPattern = "myapp://login?code={code}" }),
arguments = listOf(navArgument("code") { type = NavType.StringType })
) { backStackEntry ->
...
}
}
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.homeNavGraph() {
...
}
ログイン画面には NavHostController.navigate("login")
以外にも myapp://login
でディープリンクできるようになっています。エラーになったのは前者の navigate()
による遷移のときです。
解決方法
ディープリンクの URI で設定したクエリパラメータ(今回では code
)にデフォルト引数を設定することで解消できました。
@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.loginNavGraph(navigateToHome: () -> Unit) {
composable(
route = "login",
deepLinks = listOf(navDeepLink { uriPattern = "myapp://login?code={code}" }),
arguments = listOf(
navArgument("code") {
type = NavType.StringType
defaultValue = "" // デフォルト値を設定
}
)
) { backStackEntry ->
...
}
}
原因はハッキリとわかっていないのですが、composable()
でルートを定義するとき arguments に何かを設定(例えば code
)を設定すると、route = "login"
の場合でも route = "login?code={code}"
のように振る舞うようになっているのかなと推測しました。デフォルト値を設定すれば navigate("login?code={デフォルト値}")
と同じ動きをしてくれるのかな。。
Discussion