我在尝试使用Jetpack导航库完成动态或条件导航时遇到了一个有趣的问题。
我想到的目标是能够继续使用nav_graph.xml
来管理整个导航图,但同时允许基于某些因素进行条件导航。
我在下面添加了一些代码,这些代码显示了解决方案的发展方向。问题在于,它固有地需要大量维护才能使将来的条件逻辑起作用。
我真的希望示例中的navigateToDashboard
函数能够不带任何参数或很少更改的参数来执行。例如,也许不传递NavDirections
,而传递一些标识符,让navigateToDashboard
函数知道要返回哪个NavDirections
。
用于管理条件逻辑的类的代码。
class DynamicNavImpl(private val featureFlagService: FeatureFlagService) : DynamicNav {
override fun navigateToDashboard(navDirectionsMap: Map<Int, NavDirections>): NavDirections {
val destinationIdRes = if (featureFlagService.isDashboardV2Enabled()) {
R.id.dashboardV2Fragment
} else {
R.id.dashboardFragment
}
return navDirectionsMap[destinationIdRes] ?: handleNavDirectionsException(destinationIdRes)
}
private fun handleNavDirectionsException(destinationIdRes: Int): Nothing {
throw IllegalStateException("Destination $destinationIdRes does not have an accompanying set of NavDirections. Are you sure you added NavDirections for it?")
}
}
呼叫站点示例
navigate(
dynamicNav.navigateToDashboard(
mapOf(
Pair(R.id.dashboardFragment, PhoneVerificationFragmentDirections.phoneVerificationToDashboard()),
Pair(R.id.dashboardV2Fragment, PhoneVerificationFragmentDirections.phoneVerificationToDashboardV2())
)
)
)
navigate(
dynamicNav.navigateToDashboard(
mapOf(
Pair(R.id.dashboardFragment, EmailLoginFragmentDirections.emailLoginToDashboard()),
Pair(R.id.dashboardV2Fragment, EmailLoginFragmentDirections.emailLoginToDashboardV2())
)
)
)
查看呼叫站点,您会发现问题出在哪里。如果我想添加一个新的潜在目的地,比方说dashboardV3Fragment
,那么我必须去每个呼叫站点并添加另一个Pair
。
这几乎破坏了具有DynamicNavImpl
类的目的。所以这就是我被困住的地方。我希望能够封装决定要去哪里的目标所涉及的各种变量,但是似乎NavDirections
的实现方式却无法实现。
我经历了几种不同的方法,并且发现了一些仍然不理想的东西,但是可以用于我的用例。
我完全放弃了使用中央动态导航管理器的想法。相反,我决定使用一个“重定向”或“容器” Fragment
来决定要显示什么Fragment
。
所以这是DashboardRedirectFragment
内的新代码>
childFragmentManager.beginTransaction().replace( R.id.dashboard_placeholder, if (featureFlagService.isDashboardV2Enabled()) { DashboardV2Fragment.newInstance() } else { DashboardFragment.newInstance() } ).commit()
我使用此方法的方式是在我的导航图中注册一个名为
dashboardRedirectFragment
的新目标,而该图中需要访问仪表板的任何内容都将使用dashboardRedirectFragment
目标。
这将动态导航逻辑完全封装在重定向Fragment
中,并允许我继续按预期使用导航图。