使用导航体系结构组件,我们还可以从以下代码中进行动态导航:
navController.navigate(R.id.cartFragment)
然后,当我们需要从一个新的根目的地导航到一个新的根目的地(向后导航将关闭应用程序)时,我们无法知道当前的根目的地是什么,所以我们不知道将popUpTo目的地设置为什么。
val navigationOptions = NavOptions.Builder().setPopUpTo(R.id.???, true).build()
navController.navigate(R.id.loginFragment, null, navigationOptions)
如果我们将其设置为不在backstack中的目的地,那么我们将获得警告日志(从NavController
中的popBackStackInternal
):
“忽略popBackStack to destination*:id/splashFragment,因为在当前后堆栈上找不到它”
之所以会出现这种情况,是因为我们之前在流中也有多个案例,我们将popup设置为如此依赖于流,因此我们有不同的根目的地。
我已经研究了NavController
上所有可用的方法,并尝试了mBackStack
上的一些反射,但我无法找到清除backbackback的方法。
不知道当前根目的地时,如何清除backbackback
编辑:添加导航图示例
<fragment
android:id="@+id/navigation_cart"
android:name="ProjectsFragment_"
android:label="Cart"
tools:layout="@layout/fragment_cart" />
<fragment
android:id="@+id/loginFragment"
android:name="LoginFragment_"
android:label="Login"
tools:layout="@layout/fragment_login">
<--! Dynamic navigation to either Consent or Cart based on state -->
<action
android:id="@+id/action_login_to_home"
app:destination="@id/navigation_cart"
app:popUpTo="@id/loginFragment"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_loginFragment_to_consentFragment"
app:destination="@id/consentFragment" />
<action
android:id="@+id/action_loginFragment_to_contactFragment"
app:destination="@id/contactFragment" />
</fragment>
<fragment
android:id="@+id/splashFragment"
android:name="SplashFragment_"
android:label="SplashFragment"
tools:layout="@layout/fragment_splash">
<--! Dynamic navigation to either Onboarding, Login or Cart based on state -->
</fragment>
<dialog
android:id="@+id/consentFragment"
android:name="ConsentFragment"
android:label="ConsentFragment"
tools:layout="@layout/fragment_consent" />
<fragment
android:id="@+id/onboardingIntroFragment"
android:name="OnboardingIntroFragment_"
android:label="OnboardingIntroFragment"
tools:layout="@layout/fragment_onboarding">
<action
android:id="@+id/action_onboardingIntroFragment_to_loginFragment"
app:destination="@id/loginFragment"
app:popUpTo="@id/onboardingIntroFragment"
app:popUpToInclusive="true" />
</fragment>
<dialog
android:id="@+id/contactFragment"
android:name="ContactFragment"
android:label="ContactFragment"
tools:layout="@layout/fragment_contact" />
我们将根据上述具体案例的动态登录或片段登录。如果我们导航到登录,成功登录后导航到购物车。
在这两种情况下,我们都不知道我们的根目的地是什么,尽管无法正确设置poputo。当从Splash调用时,它是SplashFragment,当从Login调用时,它是LoginFragment,或者在签出时,它可能是CartFragment或另一个作为根目的地的片段。
如何动态地计算根目标是什么,或者只是作为导航的一部分清除后栈?
编辑2:Root destination definition我定义Root destination为要弹出的目的地,包括清除全部backbackback,såbackaction将关闭应用程序。比如飞溅-
在Android中导航到另一个片段后如何清除导航堆栈
我们最终以两种方式解决了这个问题。
1) 当我们能够从动态导航位置确定当前的根目的地时,我们将该参数解析到了动态导航器中。
object Navigator {
fun showStartFragment(navController: NavController, @IdRes currentDestination: Int) {
val navigationOptions = NavOptions.Builder().setPopUpTo(currentDestination, true).build()
if (!Settings.Intro.onboardingCompleted) {
navController.navigate(R.id.onboardingIntroFragment, null, navigationOptions)
} else {
val isLoggedIn = Settings.User.loggedIn
if (isLoggedIn) {
MainActivity.shared?.mainStateHandler?.showNextFragment(navController, currentDestination)
} else {
navController.navigate(R.id.loginFragment, null, navigationOptions)
}
}
}
}
2)但我们也遇到过这样的情况:asynendpoint响应可能会导致用户必须注销、to to expired token或用户被阻止。为了解决这个问题,我们入侵了NavController,通过反射获取根目的地
fun NavController.getRootDestination(): NavDestination? {
val mBackStack = NavController::class.java.getDeclaredField("mBackStack").let {
it.isAccessible = true
return@let it.get(this) as Deque<*>
}
for (entry in mBackStack) {
val destination = Reflector.getMethodResult(entry, "getDestination") as NavDestination
if (destination !is NavGraph) {
return destination
}
}
return null
}
object Reflector {
fun getMethodResult(`object`: Any, methodName: String): Any? {
return `object`.javaClass.getMethod(methodName).let {
it.isAccessible = true
return@let it.invoke(`object`)
}
}
}
根据文件。 我正在使用的库版本:
我目前正在学习新的Android导航架构组件 (https://developer.android.com/topic/libraries/architecture/navigation/). 我有点混淆了它的动机和概念,以下是我的不确定性: Android导航架构组件是否旨在消除在单个应用程序中使用多个活动的需要?这意味着,整个应用程序只需要一个单一活动,所有其他页面都将是片段? 在应用程序中使
我不知道如何使用新的导航架构组件,从我的主屏幕(带有连接到底部应用程序栏的浮动操作按钮)导航到没有应用程序栏的另一个屏幕。 当我点击晶圆厂时,我想要我的下一个屏幕(片段?)从右侧滑入。问题是我应该把我的
我正在我的应用程序中尝试导航架构组件。早些时候,我使用片段事务来实现以下功能。基本上,我想从导航。 碎片- 如果我正在使用导航组件并尝试 然后结果是FragmentA被FragmentB替换并且背景片段不可见。 我想知道一个解决方案,如果导航架构组件允许的话。 附言:我听说过嵌套导航主机,但从内部使用它好吗。 更新: FragmentB将有进一步交易的行动,例如: 碎片- 当用户按下后退按钮时,片
我一直在遵循导航架构组件中的文档,以了解这个新的导航系统是如何工作的。 要从一个屏幕到另一个屏幕进行/返回,您需要一个实现接口的组件。 NavHost是一个空视图,当用户在应用程序中导航时,目的地会随之交换。 但是,似乎目前只有片段实现了< code>NavHost 导航架构组件的默认NavHost实现是NavHostFragment。 所以,我的问题是: > < li> 即使我有一个可以用< c
null 在调用之前和之后,我尝试了,但都不起作用(这是有意义的:在它没有要弹出的内容之前;在它只关闭刚刚添加的片段之后)。这是否意味着唯一的方法是重写来拦截它,并确保在这些情况下不会被调用? 谢了!