The setup is like so:
Single activity app (MainActivity) with nav_graph
HomeFragment has viewPager2 with 3 subfragments
Each of these 3 fragments are same fragment with RecyclerView showing different list of posts
User can click on a post and that navigates to completely new screen/fragment (Details)
Clicking "Back" button throws exception:
java.lang.IllegalStateException: FragmentManager is already executing transactions
at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1790)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1826)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
at androidx.viewpager2.adapter.FragmentStateAdapter$FragmentMaxLifecycleEnforcer.updateFragme
So my feeling is that issue happens between ViewPager2 with RecyclerView and FragmentTransitions through navigation. Why? Well, clicking "back" arrow makes the transaction to 'home' screen, but also home screen having viewpager also deals with fragment transitions and this somehow creates the issue.
To give more context, this is how tabs/viewpager is set (in HomeFragment):
val viewPager: ViewPager2 = container.findViewById(R.id.viewPager)
viewPager.adapter = PagerAdapter(parentFragmentManager, lifecycle)
val tabLayout: TabLayout = container.findViewById(R.id.tabLayout)
val names = arrayOf("Najbolje", "Popularno", "Novo")
TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = names[position] }.attach()
Here's the adapter:
class PagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(fragmentManager, lifecycle) {
private val fragments = listOf<Fragment>(
MyListFragment.newInstance(Type.TOP),
MyListFragment.newInstance(Type.POPULAR),
MyListFragment.newInstance(Type.NEW)
)
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
}
and here's the code for setting up recyclerview:
private fun setupRecyclerView() {
val adapter = MyListAdapter(requireContext(), myService)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = layoutManager
viewModel.posts.observe(viewLifecycleOwner) { post -> adapter.submitList(posts.map { PostItem(it) }) }
addScrollListener()
}
One of the similar issues was somewhere solved by changing parentFragmentManager to childFragmentManager within setTabs method, but that creates another issue that throws exception among the lines of 'RecyclerView already has layoutManager set up'
Let me know if not enough information has been provided.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…