【问题标题】:Why Fragmenttransaction replace() acts like a add()?为什么 Fragmenttransaction replace() 的行为类似于 add()?
【发布时间】:2019-05-16 17:55:14
【问题描述】:

我有here a sample GitHub project。这只是一个通过点击底部标签来膨胀其他片段的活动:

  1. Applaunch 膨胀 Fragment 1
  2. 按 1.Tab -> 膨胀片段 1
  3. 按 2.Tab -> 膨胀片段 2
  4. 按 3.Tab -> 扩展片段 3

并且全部通过this.supportFragmentManager?.beginTransaction()?.replace() 使用。对我来说,它就像一个 FragmentTransaction.add(),因为:

当我启动应用程序(已加载片段 1)并按

  • 片段 2 的第二个选项卡(吐司片段 2)
  • 和 Fragment 3 的第三个选项卡(Toast Frag 3)
  • 然后返回按钮(Toast Frag 2)
  • 再次返回按钮(Toast Frag 1)

所有堆栈都在恢复。所以什么都没有“替换”,一切都被添加了

每当我按回时,我都想加载“Fragment 1”,这是活动的初始 Fragment。怎么样?

【问题讨论】:

  • 将日志添加到每个片段onDestroyView() 你会看到不同。

标签: android android-fragments kotlin android-fragmentactivity fragmentmanager


【解决方案1】:

我猜这是因为片段正在被替换,但它们也被添加到 BackStack 中,如下所示:

BaseActivity.kt

// Note the .addToBackStack(null)
this.supportFragmentManager?.beginTransaction()?.replace(resId, newFragment)?.addToBackStack(null)?.commit()

From Documentation for addToBackStack

将此事务添加到后台堆栈。这意味着事务将在提交后被记住,并在以后从堆栈中弹出时反转其操作。

您可能想check this question 以查看有关addreplaceaddToBackStack 之间区别的更多信息。

如果您不想“记住并恢复”片段转换,只需删除对 addToBackStack 的调用即可。

编辑

如果你总是想返回第一个片段,你可以这样做:

保留addToBackStack()。所以,导航历史将被保留

this.supportFragmentManager?.beginTransaction()?.replace(resId, 

newFragment)?.addToBackStack(null)?.commit()

MainActivityBaseActivity 上覆盖onBackPressed 并请求始终返回到第一个事务提交:

override fun onBackPressed() {
    if(this.supportFragmentManager?.getBackStackEntryCount() > 0) {
        this.supportFragmentManager?.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
    } else {
       super.onBackPressed()
    }
}

请注意这是一个测试代码,我无法验证。另外,我对 Kotlin 不熟悉。所以,这是我能提供的最好的代码......测试并让我知道结果......无论如何,你可以得到这个想法。

另一种选择:

删除addToBackStack():

this.supportFragmentManager?.beginTransaction()?.replace(resId, newFragment)?.addToBackStack(null)?.commit()

然后,您必须手动控制当用户按下后退键时应显示哪个片段...类似于:

private var int : mCurrentFragment = 1

private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
    when (item.itemId) {
        R.id.navigation_home -> {
            mCurrentFragment = 1
            ...
        }
        R.id.navigation_dashboard -> {
            mCurrentFragment = 2
            ...
        }
        R.id.navigation_notifications -> {
            mCurrentFragment = 3
            ...
        }
    }
    false
}

override fun onBackPressed() {
    if(mCurrentFragment != 1) {
        replaceFragment(R.id.container_main_layout, Fragment1())
    } else {
       super.onBackPressed()
    }
}

【讨论】:

  • 删除它。但是现在,一个背压终止了活动。我怎样才能保持在活动中并在应用刚刚启动时为 Fragment 1 充气?
  • @NoamSilverstein 我在答案中添加了更多信息。看看吧
猜你喜欢
  • 2014-09-22
  • 1970-01-01
  • 2012-11-22
  • 2018-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
相关资源
最近更新 更多