Change theme
Help
Press space for more information.
Show links for this issue (Shortcut: i, l)
Copy issue ID
Previous Issue (Shortcut: k)
Next Issue (Shortcut: j)
Sign in to use full features.
Vote: I am impacted
Notification menu
Refresh (Shortcut: Shift+r)
Go home (Shortcut: u)
Pending code changes (auto-populated)
View issue level access limits(Press Alt + Right arrow for more information)
Unintended behavior
View staffing
Description
This behavior leads to incorrect navigation outcomes, where only the first registered destination is matched, even if the deep link pattern is intended for a different destination.
Steps to reproduce:
1. Define Destinations:
@Serializable
data class EditPhone(val type: String = "phone")
fun NavGraphBuilder.editPhoneScreen(navController: NavController) {
composable<EditPhone>(
deepLinks = navDeepLink<EditPhone> { basePath = "app://open/verify" }
) {
....
}
}
@Serializable
data class EditEmail(val type: String = "email")
fun NavGraphBuilder.editEmailScreen(navController: NavController) {
composable<EditEmail>(
deepLinks = navDeepLink<EditEmail> { basePath = "app://open/verify" }
) {
....
}
}
2. Attempt to Navigate:
- Navigate to app://open/verify?type=phone.
- Navigate to app://open/verify?type=email.
3.Result:
Both navigation attempts resolve to the EditEmail screen, as it is registered first.
Expected Behavior:
The system should differentiate destinations based on their associated type-safe classes, even if the URI patterns are identical.
Root Cause:
The current navigation system resolves deep links based on the URI pattern alone, ignoring the associated type-safe classes. When two destinations share the same pattern (e.g., app://open/verify?type={type}), only the first registered destination is matched, regardless of the type-safe class.
Workaround:
To make deep links work correctly, you can define the deep links explicitly using uriPattern, like this:
For EditPhone:
deepLinks = navDeepLink { uriPattern = "app://open/verify?type=phone" }
For EditEmail:
deepLinks = navDeepLink { uriPattern = "app://open/verify?type=email" }
While this workaround resolves the issue, it prevents the use of type-safe navigation, which is a key benefit of the system.
Pop-up Navigation Considerations:
Additionally, when popping screens, you should use route names instead of instances of the type-safe classes.
val navOptions = NavOptions.Builder()
.setPopUpTo(
route = EditPhone::class.qualifiedName.toString(),
inclusive = true
)
.build()
This ensures correct pop-up behavior, whereas using the instance of EditPhone() would not work as expected.
Proposed Solution
The navigation system should treat destinations as unique based on their associated type-safe classes, even if their URI patterns overlap. This would ensure:
- Proper differentiation between destinations.
- Consistency with the expectations set by type-safe navigation.