FragmentManager 之 addToBackStack 作用

217 阅读2分钟

FragmentManager 管理 Fragment 返回堆栈。在运行时,FragmentManager 可以执行添加或移除 Fragment 等返回堆栈操作来响应用户互动。每一组更改作为一个单元(称为 FragmentTransaction)一起提交。

当用户点按设备上的返回按钮时,或者你调用 FragmentManager.popBackStack() 时,最上面的 Fragment 事务会从堆栈中弹出。如果堆栈上没有更多 Fragment 事务,并且你没有使用子 Fragment,则返回事件会向上传递到 Activity。

弹出返回堆栈时,所有这些操作会作为一项原子化操作反转。不过,如果你在调用 popBackStack() 之前提交了其他事物,并且你没有对事务使用 addToBackStack(), 则这些操作不会反转。

案例1

如果没有对事务使用 addToBackStack(), 在 MainActivity 中点击设备的返回按钮,整个应用退出。

class MainActivity : AppCompatActivity() {
    companion object {
        private const val TAG = "MainActivity"
    }

    private lateinit var mBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        loadFragment(MainFragment(), "mainFragment", false)
    }

    private fun loadFragment(fragment: Fragment, tag: String, addToBackStack: Boolean) {
        val transaction = supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, fragment, tag)
        if (addToBackStack) {
            transaction.addToBackStack(tag)
        }
        transaction.commit()
    }
}

案例2

如果对事务使用 addToBackStack(), 在 MainActivity 中点击设备的返回按钮,MainFragment 会退出,MainActivity 会在返回堆栈栈顶。

class MainActivity : AppCompatActivity() {
    companion object {
        private const val TAG = "MainActivity"
    }

    private lateinit var mBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        loadFragment(MainFragment(), "mainFragment", true)
    }

    private fun loadFragment(fragment: Fragment, tag: String, addToBackStack: Boolean) {
        val transaction = supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, fragment, tag)
        if (addToBackStack) {
            transaction.addToBackStack(tag)
        }
        transaction.commit()
    }
}

案例3

在 btnMain, btnFirst 和 btnMain 三个点击事件中的 FragmentTransaction 都使用 addToBackStack, 点击生成的 FragmentTransaction 都会存入返回堆栈中,点击设备的返回键,则会按顺序逐一复原

class MainActivity : AppCompatActivity() {
    companion object {
        private const val TAG = "MainActivity"
    }

    private lateinit var mBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        loadFragment(MainFragment(), "mainFragment", false)

        mBinding.btnMain.setOnClickListener(object: View.OnClickListener {
            override fun onClick(p0: View?) {
                Log.i(TAG, "BtnMain click")
                loadFragment(MainFragment(), "mainFragment", true)
            }
        })

        mBinding.btnFirst.setOnClickListener(object: View.OnClickListener {
            override fun onClick(p0: View?) {
                Log.i(TAG, "BtnFirst click")
                loadFragment(FirstFragment(), "firstFragment", true)
            }
        })

        mBinding.btnSecond.setOnClickListener(object: View.OnClickListener {
            override fun onClick(p0: View?) {
                Log.i(TAG, "BtnSecond click")
                loadFragment(SecondFragment(), "secondFragment", true)
            }
        })
    }

    private fun loadFragment(fragment: Fragment, tag: String, addToBackStack: Boolean) {
        val transaction = supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, fragment, tag)
        if (addToBackStack) {
            transaction.addToBackStack(tag)
        }
        transaction.commit()
    }
}