如何使用Jetpack Navigation创建动态/条件导航?

4
我在尝试使用 Jetpack Navigation 库实现动态或条件导航时遇到了一个有趣的问题。
我想实现的目标是继续使用 `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 的实现方式,我做不到。

1个回答

3

我尝试了几种不同的方法,最终找到了一种在我的使用场景下仍然不理想但可行的方案。

我完全放弃了使用中央动态导航管理器的想法。相反,我决定使用一个“重定向”或“容器”Fragment来决定显示哪个Fragment

所以这里是DashboardRedirectFragment中的新代码

childFragmentManager.beginTransaction().replace(
                R.id.dashboard_placeholder,
                if (featureFlagService.isDashboardV2Enabled()) {
                    DashboardV2Fragment.newInstance()
                } else {
                    DashboardFragment.newInstance()
                }
        ).commit()

我使用的方法是在我的导航图中注册一个名为dashboardRedirectFragment的新目标,任何需要访问仪表板的内容都使用dashboardRedirectFragment目标。

这完全封装了重定向Fragment中的动态导航逻辑,并允许我继续按预期使用我的导航图。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接