7

信息:

我以编程NavHostFragment方式为应用程序的每个功能插入一个。每个NavHostFragment都有自己的导航图。Dagger 通过使用FragmentFactory特定于每个功能的特性来提供它们。它是具有 MVVM 架构的Single Activity结构。

回购:https ://github.com/mitchtabian/DaggerMultiFeature/tree/nav-component-backstack-bug

签出分支“nav-component-backstack-bug”。


问题

导航到图表时,片段不会被添加到后台堆栈。添加的唯一片段是最近访问过的片段。因此堆栈大小始终保持为 1。

最初我认为这是因为我没有将其设置FragmentFactory为,ChildFragmentManager但这并没有改变任何东西。请参阅下面的代码片段以获取相关代码。或者签出项目并运行它。我有日志打印出当前在后台堆栈中的片段ChildFragmentManager,还有SupportFragmentManager. 两者的大小都为 1。


Feature1NavHostFragment.kt

这是习惯之一NavHostFragment。伴随对象中的create()函数是我创建它们的方式。


class Feature1NavHostFragment
@Inject
constructor(
    private val feature1FragmentFactory: Feature1FragmentFactory
): NavHostFragment(){

    override fun onAttach(context: Context) {
        ((activity?.application) as BaseApplication)
            .getAppComponent()
            .feature1Component()
            .create()
            .inject(this)
        childFragmentManager.fragmentFactory = feature1FragmentFactory
        super.onAttach(context)
    }

    companion object{

        const val KEY_GRAPH_ID = "android-support-nav:fragment:graphId"

        @JvmStatic
        fun create(
            feature1FragmentFactory: Feature1FragmentFactory,
            @NavigationRes graphId: Int = 0
        ): Feature1NavHostFragment{
            var bundle: Bundle? = null
            if(graphId != 0){
                bundle = Bundle()
                bundle.putInt(KEY_GRAPH_ID, graphId)
            }
            val result = Feature1NavHostFragment(feature1FragmentFactory)
            if(bundle != null){
                result.arguments = bundle
            }
            return result
        }
    }

}

MainActivity.kt

这是我如何NavHostFragment在 MainActivity 中创建 's 的示例。


val newNavHostFragment = Feature1NavHostFragment.create(
                                  getFeature1FragmentFactory(),
                                  graphId
                         )
supportFragmentManager.beginTransaction()
    .replace(
        R.id.main_nav_host_container,
        newNavHostFragment,
        getString(R.string.NavHostFragmentTag)
    )
    .setPrimaryNavigationFragment(newNavHostFragment)
    .commit()


Feature1MainFragment.kt

这是我如何导航到图中的其他片段的示例。


btn_go_next.setOnClickListener {
    findNavController().navigate(R.id.action_feature1MainFragment_to_feature1NextFragment)
}


概括

就像我说的,在每个片段中,我都在为ChildFragmentManager和打印 backstack SupportFragmentManager。两者都有一个恒定的大小。当我导航到图表而不是添加到堆栈中时,就好像片段正在被替换。

无论如何,感谢您阅读本文,我将不胜感激。

4

1 回答 1

2

看起来像是我的一个误解(和一个错误,也是我的一部分)。

如果您遍历其中的片段,childFragmentManager它只会出于某种原因显示最顶部的片段。

例子

val navHostFragment = supportFragmentManager
            .findFragmentByTag(getString(R.string.NavHostFragmentTag)) as NavHostFragment
val fragments = navHostFragment.childFragmentManager.fragments
for(fragment in fragments){
    // Only prints a single fragment, no matter the backstack size
}

但是,如果您像这样打印 backstack 大小,您将得到正确的答案。

val navHostFragment = supportFragmentManager
            .findFragmentByTag(getString(R.string.NavHostFragmentTag)) as NavHostFragment
val backstackCount = navHostFragment.childFragmentManager.backStackEntryCount
println("backstack count: $backstackCount")

归根结底,这种误解使我相信这些片段没有被添加到后台堆栈中。一切都很好。

于 2020-01-23T21:23:50.303 回答