#android #navigation #android-architecture-components #android-architecture-navigation
#Android #навигация #android-архитектура-компоненты #android-архитектура-навигация
Вопрос:
Мой навигационный график имеет auth
подграф, содержащий LoginFragment и SignUpFragment:
<navigation
android:id="@ id/auth"
app:startDestination="@id/loginFragment">
<fragment
android:id="@ id/signUpFragment"
[...]
<fragment
android:id="@ id/loginFragment"
[...]
</fragment>
[...]
</navigation>
Я хочу проверить, находится ли какой-либо из этих 2 пунктов назначения в данный момент в бэкстеке. Но вместо того, чтобы проверять каждое место назначения отдельно, вот так:
val currentDestId = navController.currentDestination?.id
if (currentDestId != R.id.loginFragment amp;amp; currentDestId != R.id.signUpFragment) {
navController.navigate(
NavGraphDirections.actionGlobalLogin()
)
}
Я думаю, было бы чище просто проверить, находится ли в данный момент график аутентификации в заднем стеке.
Мой текущий подход заключается в следующем:
val authBackStack = try {
navController.getBackStackEntry(R.id.auth)
} catch (t: Throwable) {
null
}
if (authBackStack == null) {
navController.navigate(
NavGraphDirections.actionGlobalLogin()
)
}
Идея здесь заключается в том, что getBackStackEntry
выдает IllegalStateException
, если переданный адресат (или график в данном случае) в данный момент не находится в заднем стеке. Мы используем это исключение в качестве индикатора, чтобы узнать, находится ли наш график в данный момент в заднем стеке или нет.
Является ли это допустимым подходом или он сломается в определенных сценариях? Или, может быть, есть даже лучший подход, чтобы проверить, содержит ли задний стек назначения определенного подграфа?
Комментарии:
1. Может быть, это будет полезно. popBackStack возвращает логическое значение. Основываясь на результатах, мы знаем, был ли пункт назначения в стеке.
val hasAuthDestionation = findNavController().popBackStack(R.id.auth, false) if (!hasAuthDestionation) { findNavController().navigate(R.id.newDestination) }
Кроме того, вы можете использовать инклюзивное «true», если это необходимо.
Ответ №1:
Это правильный подход, но вы можете скрыть его как функцию расширения следующим образом:
fun NavController.isOnBackStack(@IdRes id: Int): Boolean = try { getBackStackEntry(id); true } catch(e: Throwable) { false }
Таким образом, вы фактически получаете желаемое логическое значение, скрывая поток управления на основе исключений (это требование из-за API, который предоставляет Jetpack Navigation).