关于FragmentManager中findFragmentByTag返回null及回退栈的疑问
先帮你拆解几个核心概念,把你遇到的问题逐个对应上:
1. 关于BackStackEntryCount的本质
你对这个属性的理解是正确的——它统计的是调用addToBackStack()保存的事务总数,和当前存活的Fragment数量、回退栈里实际能恢复的状态没有直接关联。
你步骤5的replace操作应该是调用了addToBackStack()(否则BackStackEntryCount不会变成5),所以这个替换事务被追加到了回退栈的末尾,计数自然+1。回退栈里存的是「事务操作记录」,不是Fragment实例本身,哪怕这个事务销毁了之前的所有Fragment,已经保存的事务记录依然会留在回退栈里,计数也不会减少。
2. 为什么findFragmentByTag("A")返回null,但fragments列表里有FragmentA?
这是关键误区:你步骤5的replace操作添加的新FragmentA并没有设置标签"A"!
回忆下replace的重载方法:
- 如果用的是
replace(int containerViewId, Fragment fragment):这个新Fragment不会被设置任何标签 - 只有用
replace(int containerViewId, Fragment fragment, String tag)时,才会给新Fragment绑定指定标签
你之前步骤1、3添加的FragmentA是带标签"A"的,但步骤5的replace会销毁容器内所有现存Fragment(包括之前那两个带标签"A"的FragmentA实例),然后添加一个全新的、无标签的FragmentA实例。
而findFragmentByTag("A")只会查找带有标签"A"的存活Fragment实例,这个新实例没有标签,所以返回null;但supportFragmentManager.fragments是FragmentManager当前管理的所有存活Fragment的集合,不管有没有标签,所以能看到这个新的FragmentA。
如果把步骤5的代码改成:
supportFragmentManager.beginTransaction() .replace(R.id.container, FragmentA(), "A") // 这里加上标签"A" .addToBackStack(null) .commit()
再调用findFragmentByTag("A")就能拿到这个新的FragmentA实例了。
3. 纠正你对replace操作的误解
步骤5的replace并没有移除回退栈中所有现有事务,它只是做了三件事:
- 移除容器内的所有Fragment(销毁它们的实例,从FragmentManager的存活列表中移除)
- 添加新的FragmentA到容器中
- 把这个「替换事务」添加到回退栈(因为你调用了addToBackStack)
当你按返回键时,回退栈会回滚这个替换事务:销毁步骤5添加的FragmentA,恢复步骤4结束时的状态(容器内是FragmentC,回退栈回到4的状态)。
内容的提问来源于stack exchange,提问作者Zaid Mirza

