Android Bottom Navigation切换时qponFragment刷新问题求助
嘿,我发现你遇到的问题根源其实不是setRetainInstance(true)没起作用,而是每次切换底部导航时,你都在创建全新的Fragment实例,导致之前保留的实例根本没被用上!
问题原因拆解
看你的createQponFragment()方法:
fun createQponFragment() { val transaction = manager.beginTransaction() val fragment = qponFragment() // 每次都new一个新实例! transaction.replace(R.id.fragmentholder,fragment) transaction.addToBackStack(null) transaction.commit() }
这里每次调用都会创建一个全新的qponFragment对象,哪怕你在Fragment里设置了setRetainInstance(true),但这个新实例和之前保留的完全没关系,所以切换回来自然会重新刷新内容。而且replace方法会销毁容器里原来的Fragment,这也会导致状态丢失。
修复方案:复用Fragment实例 + 使用hide/show替代replace
我们可以通过保存Fragment的实例引用,用add+hide/show的方式来管理Fragment,这样就能保留Fragment的状态了:
步骤1:在MainActivity中保存Fragment实例
首先在MainActivity的类里添加成员变量,用来存储各个Fragment的实例:
class MainActivity : AppCompatActivity() { private var mFirebaseAnalytics: FirebaseAnalytics? = null // 保存Fragment实例 private var qponFragment: qponFragment? = null private var meFragment: meFragment? = null private var toolFragment: toolFragment? = null private var tutorialFragment: tutorialFragment? = null // ... 其他原有代码 }
步骤2:修改Fragment创建方法,复用实例
把原来的createQponFragment()等方法改成以下逻辑:先隐藏所有其他Fragment,然后判断目标Fragment是否存在,不存在就创建并add,存在就直接show:
val manager = supportFragmentManager fun createQponFragment() { val transaction = manager.beginTransaction() hideAllFragments(transaction) // 先隐藏其他Fragment if (qponFragment == null) { qponFragment = qponFragment() transaction.add(R.id.fragmentholder, qponFragment!!) } else { transaction.show(qponFragment!!) } transaction.commit() } fun createMeFragment() { val transaction = manager.beginTransaction() hideAllFragments(transaction) if (meFragment == null) { meFragment = meFragment() transaction.add(R.id.fragmentholder, meFragment!!) } else { transaction.show(meFragment!!) } transaction.commit() } fun createToolFragment() { val transaction = manager.beginTransaction() hideAllFragments(transaction) if (toolFragment == null) { toolFragment = toolFragment() transaction.add(R.id.fragmentholder, toolFragment!!) } else { transaction.show(toolFragment!!) } transaction.commit() } fun createTutorialFragment() { val transaction = manager.beginTransaction() hideAllFragments(transaction) if (tutorialFragment == null) { tutorialFragment = tutorialFragment() transaction.add(R.id.fragmentholder, tutorialFragment!!) } else { transaction.show(tutorialFragment!!) } transaction.commit() }
步骤3:添加隐藏所有Fragment的辅助方法
在MainActivity里添加一个工具方法,用来统一隐藏所有已存在的Fragment,避免重叠:
private fun hideAllFragments(transaction: FragmentTransaction) { qponFragment?.let { transaction.hide(it) } meFragment?.let { transaction.hide(it) } toolFragment?.let { transaction.hide(it) } tutorialFragment?.let { transaction.hide(it) } }
步骤4:移除不必要的返回栈操作
原来的transaction.addToBackStack(null)可以去掉,因为底部导航的切换逻辑通常不需要加入返回栈(否则按返回键会回到之前的Fragment,不符合用户预期)。
额外优化:可以去掉setRetainInstance(true)
用add+hide/show的方式,Fragment实例会一直被Activity持有,不会被销毁,所以qponFragment里的setRetainInstance(true)其实可以移除了,状态依然会被保留。
小提示
按照Kotlin的命名规范,类名应该首字母大写,建议把qponFragment改成QponFragment,meFragment改成MeFragment之类的,代码可读性会更好~
内容的提问来源于stack exchange,提问作者GPH

