ViewPager2+TabLayout下Hilt Fragment onAttach多次调用崩溃问题解决
ViewPager2 + Hilt Fragment 二次重载崩溃解决方案
崩溃信息
java.lang.IllegalStateException: onAttach called multiple times with different Context! Hilt Fragments should not be retained.
问题根源
代码中ResourceStore提前创建并缓存了所有DashboardNew Fragment实例,FragmentStateAdapter的createFragment方法直接返回这些缓存的旧实例。当宿主TabLayoutDemo Fragment重建时,ViewPager2尝试将旧Fragment实例重新绑定到新的Context上,但Hilt绑定的Fragment不允许重复关联不同Context——Hilt已为旧实例注入了与旧Context绑定的依赖,重复attach会导致上下文冲突,触发崩溃。
修复步骤
1. 修改FragmentStateAdapter的createFragment方法
不再复用提前创建的Fragment实例,每次调用createFragment时生成新实例:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.viewpager.adapter = object : FragmentStateAdapter(this) { override fun createFragment(position: Int): Fragment { // 每次创建新的Fragment实例,避免复用缓存的旧实例 return DashboardNew.create() } override fun getItemCount(): Int { return ResourceStore.tabList.size } } TabLayoutMediator(binding.tabs, binding.viewpager) { tab, position -> tab.text = getString(ResourceStore.tabList[position]) }.attach() }
2. 移除缓存的Fragment实例列表
删除ResourceStore中提前创建的pagerFragments,Fragment实例由FragmentStateAdapter按需创建即可:
interface ResourceStore { companion object { val tabList = listOf( R.string.Dashboard, R.string.Tracking, R.string.Fastags,R.string.Reports, R.string.Documents, R.string.Maintance, R.string.Alerts, R.string.Device ) } }
额外注意事项
确保DashboardNew Fragment没有设置setRetainInstance(true),Hilt官方明确禁止保留Hilt Fragment实例,这也是错误提示中强调的核心限制。
内容的提问来源于stack exchange,提问作者Bolt UIX
相关产品推荐
相关产品推荐

