首页 > 解决方案 > 同一片段的多个实例:Android 导航组件

问题描述

我创建了一个类来为我的应用程序中的每个选项卡处理不同的返回堆栈,因此我使用具有“currentcontroller”字段的不同导航控制器来获取当前的:

   private val navNewsController: NavController = obtainNavHostFragment(fragmentTag = "news", containerId = R.id.newsTabContainer).navController.apply {
        graph = navInflater.inflate(R.navigation.navigation_graph_main).apply {
            startDestination = startDestinations.getValue(R.id.tab_news)
        }
        addOnDestinationChangedListener { controller, destination, arguments ->
            onDestinationChangedListener?.onDestinationChanged(controller, destination, arguments)
        }
    }

    val navFormController: NavController = obtainNavHostFragment(fragmentTag = "form", containerId = R.id.formTabContainer).navController.apply {
        graph = navInflater.inflate(R.navigation.navigation_graph_main).apply {
            startDestination = startDestinations.getValue(R.id.tab_form)
        }
        addOnDestinationChangedListener { controller, destination, arguments ->
            onDestinationChangedListener?.onDestinationChanged(controller, destination, arguments)
        }
    }

  private fun obtainNavHostFragment(
            fragmentTag: String,
            containerId: Int
    ): NavHostFragment {
        val existingFragment = mainActivity.supportFragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment?
        existingFragment?.let { return it }

        val navHostFragment = NavHostFragment.create(R.navigation.navigation_graph_main)
        mainActivity.supportFragmentManager.beginTransaction()
                .add(containerId, navHostFragment, fragmentTag)
                .commitNowAllowingStateLoss()
        return navHostFragment
    }

当我切换标签时,我只需更改“currentController”:

fun switchTab(tabId: Int, goToRoot: Boolean = false) {
    currentFragment()?.onPause()

    currentTabId = tabId

    when (tabId) {
        R.id.tab_news -> {
            currentController = navNewsController
            invisibleTabContainerExcept(newsTabContainer)
        }
        R.id.tab_form -> {
            currentController = navFormController
            invisibleTabContainerExcept(formTabContainer)
        }
....

所以我有这个从新闻和表单打开的 FragmentA。

每当我从新闻打开 FragmentA 然后从表单打开 FragmentA 时,新闻中的 FragmentA 就会重新加载从表单打开的新参数。

我尝试在导航图中使用不同的操作,我尝试用不同的 id 声明片段两次,然后为各自的 id 声明不同的操作。我还尝试通过扩展原始的“AFragemnt”来制作“newsAFragment”和“formAFragment”,但仍然不起作用。

我还尝试了导航选项:

NavOptions.Builder().setLaunchSingleTop(false).build()

如何在导航图中使用同一片段类的多个实例?

标签: androidandroid-architecture-navigation

解决方案


原来问题出在 ViewModel 而不是片段本身。它使用的是相同的视图模型实例。相反,我知道为 viewmodelstore 中的每个实例使用唯一键


推荐阅读