活动和片段问题中的导航控制器

Posted

技术标签:

【中文标题】活动和片段问题中的导航控制器【英文标题】:NavController in Activity & Fragment Issue 【发布时间】:2021-05-05 18:30:59 【问题描述】:

在我的Activity 中,我在OnCreate 中设置了NavController

navController = findNavController(this, R.id.NavHostFragment)

在我的Fragments 中,我在onViewCreated 中设置了NavController

navController = Navigation.findNavController(view)

Activity 仅在单击项目时从NavigationView 导航到几个Fragments(例如SitesFragmentContactsFragmentTasksFragment 等),如下所示:

            R.id.nav_sites_fragment -> 
                navController.popBackStack(R.id.sitesFragment, true)
                navController.navigate(R.id.sitesFragment)
            

Fragments中,点击事件(在RecyclerViews中主要指向其他Fragment,如SiteFragmentContactFragmentTaskFragment等)处理如下:

            if (!navController.popBackStack(R.id.siteFragment, false)) 
                // not in BackStack
                navController.navigate(R.id.action_contactFragment_to_siteFragment)
                

问题是,即使我在Activity 操作中弹出BackStack,来自Fragment 操作的片段仍保留在后台堆栈中。..

我认为我对 backstack 的理解不正确,因为我不确定发生了什么 - 但也许我创建了两个独立的 NavController 实例?

编辑:虽然我看过这篇帖子How to clear navigation Stack after navigating to another fragment in android,但我仍然发现相同的行为。 Activity 中的 PopBackStack 没有清除添加到 backstack 的 Fragments..

例如:

SITES -> SITE -> CONTACT -> CONTACTS 应该删除前三个片段,但 backpress 仍然返回到 CONTACT..

【问题讨论】:

【参考方案1】:

好的,所以我找到了这个帖子https://github.com/android/architecture-components-samples/issues/767。

我稍微修改了代码,在我的活动中我有以下功能:

    private fun navigateWithClearStack(destination: Int) 
        val navController = findNavController(R.id.NavHostFragment)
        val navHostFragment: NavHostFragment = supportFragmentManager.findFragmentById(R.id.NavHostFragment) as NavHostFragment
        val inflater = navHostFragment.navController.navInflater
        val graph = inflater.inflate(R.navigation.business_navigation)
        graph.startDestination = destination

        navController.graph = graph
    

然后,我在哪里处理 NavigationView 点击:

    override fun onNavigationItemSelected(item: MenuItem): Boolean 

        when (item.itemId) 

            R.id.nav_sites_fragment -> navigateWithClearStack(R.id.sitesFragment)
            R.id.nav_projects_fragment -> navigateWithClearStack(R.id.projectsFragment)
            R.id.nav_contacts_fragment -> navigateWithClearStack(R.id.contactsFragment)
            R.id.nav_tasks_fragment -> navigateWithClearStack(R.id.tasksFragment)
            
            R.id.nav_profile_fragment -> makeToast("Todo: Profile Fragment")
            R.id.nav_settings_fragment -> makeToast("Todo: Settings Fragment")

        
        business_drawer_layout.closeDrawer(GravityCompat.START)
        return true
    

因此,当用户在应用程序中导航时,片段被添加到 BackStack(使用 popUpTo 处理重复项),但是当用户单击快捷方式回到“开始”片段之一时,图表被替换,从而清除 BackStack..我认为这很整洁。

【讨论】:

以上是关于活动和片段问题中的导航控制器的主要内容,如果未能解决你的问题,请参考以下文章

导航组件:找不到 NavController

使用导航架构组件添加(而不是替换)片段

导航组件:找不到NavController

如何使用 UINavigationController 中的所有视图和导航控制器的导航控件检测用户活动?

如何在主片段中单击按钮时打开导航抽屉?

在导航控制器中杀死片段