Fragment 事务与 Back Stack · AndroidX 源码指南
AAndroidX 源码指南
Fragment
应用基础 · androidx.fragment

Fragment 事务与 Back Stack1.9.0-rc01

commit、commitNow、addToBackStack 和 state loss 的实际边界。

最后更新 2026-08-01

基本事务

supportFragmentManager.commit {
    setReorderingAllowed(true)
    replace<DetailFragment>(R.id.container, args = args)
    addToBackStack("detail")
}
API行为
commit()异步排队到主线程执行(默认)
commitNow()同步立即执行;不能与 addToBackStack 同用
commitAllowingStateLoss()状态已保存后仍允许提交(有风险)
commitNowAllowingStateLoss()同步 + 允许状态丢失

普通页面切换优先异步 commit——让 FragmentManager 按正常队列和生命周期完成操作。

addToBackStack:可返回

supportFragmentManager.commit {
    replace<A>(R.id.container)
    addToBackStack("a")   // 记录:返回时回到之前状态
}

// 返回
supportFragmentManager.popBackStack()

// 按 name 弹出
supportFragmentManager.popBackStack("detail", PopBackStackFlags.INCLUSIVE)
  • addToBackStack(name) 把当前事务状态压入返回栈。
  • 返回时逆序回放事务(旧 Fragment 恢复而不是重建)。
  • setReorderingAllowed(true) 允许优化中间状态,back stack 事务获得正确生命周期/动画。

state loss:为什么不要乱用 AllowingStateLoss

// ❌ 危险:onSaveInstanceState 之后 commit,进程恢复时可能丢
if (savedInstanceState == null) {
    supportFragmentManager.commitAllowingStateLoss { ... }
}

commitAllowingStateLoss 允许在状态已保存后提交,但该变化可能在进程恢复时消失。它不是解决生命周期错误的通用方案——正确做法是把导航事件放回可提交的生命周期窗口(onCreate 之后、状态保存之前)。

事务的三种操作

supportFragmentManager.commit {
    add<A>(R.id.container)          // 添加(不销毁现有)
    remove(existingFragment)        // 移除
    replace<B>(R.id.container)      // 移除旧 + 添加新
    hide(fragment) / show(fragment) // 隐藏/显示(保留状态)
}

hide/show 保留 Fragment 状态(适合 tab);replace 销毁旧实例(回收内存)。

常见陷阱

  • commitNow + addToBackStack:IllegalStateException。
  • 状态保存后 commit:IllegalStateException 或状态丢失。
  • replace 后 View 状态丢失:替换会销毁旧 Fragment。
  • 忘 setReorderingAllowed:动画/生命周期异常(新版本默认 false)。
  • Fragment 引用泄漏:事务后仍持有旧 Fragment 引用。

复制即用

class MainFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.openDetail.setOnClickListener {
            parentFragmentManager.commit {
                setReorderingAllowed(true)
                replace<DetailFragment>(
                    R.id.fragment_container,
                    args = Bundle().apply { putString("id", itemId) },
                )
                addToBackStack("detail")
            }
        }
    }
}

要点

  • 异步 commit 是默认;commitNow 同步但不能进返回栈。
  • addToBackStack 让事务可返回;返回栈逆序回放。
  • 状态保存后提交用 AllowingStateLoss 但有丢失风险——把导航放回正确窗口。
  • hide/show 保状态,replace 换实例。

相关页面