宿主Fragment销毁后ViewPager2内TabFragment实例未被回收问题咨询
问题根因
- 第一:
FragmentStateAdapter使用不符合规范。你预先创建了所有TabFragment实例存在列表中传入适配器,FragmentStateAdapter本应负责内部创建和回收Fragment实例,外部持有这些实例的强引用会导致Fragment无法被GC回收,自然不会触发销毁生命周期。 - 第二:适配器绑定了错误的生命周期所有者。你给
FragmentStateAdapter传入了FragmentActivity作为参数,导致子Fragment的生命周期和Activity绑定,而不是和宿主HostFragment绑定,HostFragment销毁时Activity仍存活,所以不会主动销毁子TabFragment。
修复方案
- 重写适配器,移除外部传入的Fragment实例列表,改为适配器内部按需创建Fragment实例,同时绑定HostFragment的
childFragmentManager和生命周期:
class LessonTabsAdapter( hostFragment: Fragment, private val pageCount: Int ) : FragmentStateAdapter(hostFragment.childFragmentManager, hostFragment.lifecycle) { override fun getItemCount() = pageCount override fun createFragment(position: Int): Fragment { return when(position) { 0 -> TabFragment1() 1 -> TabFragment2() 2 -> TabFragment3() else -> throw IllegalArgumentException("invalid position $position") } } }
如果需要给TabFragment传递参数,可通过newInstance方式封装参数,不要提前创建Fragment实例:
// 示例:TabFragment1的伴生类创建实例方法 companion object { fun newInstance(id: String) = TabFragment1().apply { arguments = bundleOf("key_id" to id) } } // createFragment中调用 return TabFragment1.newInstance("your_param")
- 在HostFragment中初始化适配器时,传入当前HostFragment实例即可:
// HostFragment的onViewCreated方法中 viewPager2.adapter = LessonTabsAdapter(this, 3)
- 主动释放TabFragment占用的资源,避免内存泄漏:
在TabFragment的onDestroyView中释放音视频播放器、解绑所有监听、置空强引用:
override fun onDestroyView() { super.onDestroyView() // 释放ExoPlayer player.release() // 释放自定义MediaPlayer mediaPlayer?.release() mediaPlayer = null // 其他需要解绑的监听、置空的引用统一在这里处理 }
完成以上修改后,HostFragment出栈销毁时,对应的TabFragment就会正常触发完整销毁生命周期,不会再出现实例残留的问题。
内容的提问来源于stack exchange,提问作者Hayk Nahapetyan
相关产品推荐
相关产品推荐

