android - 片段转换的 ViewPager 和 RecyclerView 问题
问题描述
设置是这样的:
带有 nav_graph 的单活动应用程序 (MainActivity)
HomeFragment 有 viewPager2 和 3 个子片段
这 3 个片段中的每一个都是相同的片段,RecyclerView 显示不同的帖子列表
用户可以单击帖子并导航到全新的屏幕/片段(详细信息)
单击“返回”按钮会引发异常:
java.lang.IllegalStateException: FragmentManager 已经在 androidx.fragment 的 androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1826) 的 androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1790) 处执行事务。 app.BackStackRecord.commitNow(BackStackRecord.java:297) 在 androidx.viewpager2.adapter.FragmentStateAdapter$FragmentMaxLifecycleEnforcer.updateFragme
所以我的感觉是这个问题发生在 ViewPager2 与 RecyclerView 和 FragmentTransitions 通过导航之间。为什么?好吧,单击“返回”箭头会使事务转到“主”屏幕,但具有 viewpager 的主屏幕也处理片段转换,这会以某种方式产生问题。
为了提供更多上下文,这是设置选项卡/viewpager 的方式(在 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()
这是适配器:
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]
}
}
这是设置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()
}
类似的问题之一是通过在 setTabs 方法中将 parentFragmentManager 更改为 childFragmentManager 来解决的,但这会产生另一个问题,在“RecyclerView 已设置 layoutManager”的行中引发异常
如果没有提供足够的信息,请告诉我。
解决方案
您使用的是错误的FragmentManager
- 对于完全包含在另一个布局中的每个片段(例如您的ViewPager2
托管片段),您必须使用它childFragmentManager
来正确嵌套片段。
viewPager.adapter = PagerAdapter(childFragmentManager, lifecycle)
这不仅需要正确恢复您的状态(使用活动supportFragmentManager
不会做的事情),而且要确保父片段首先经历其状态转换,然后子片段才会经历他们的转换,修复“已经执行交易”的问题。
推荐阅读
- python - 两个数据帧中短语的文本比较,并在匹配短语与序列和索引处获得输出
- touch - Fullpage.js - 在“带触控的笔记本电脑”上无法正常工作
- c - 如何在没有轮询的情况下判断 fb_var_screeninfo 是否更改
- node.js - 如何使用 Node.js 在本地主机上播放 IBM Watson Text To Speech 音频
- javascript - 键入时防止重新呈现主菜单
- c++ - 如何加载(或映射)文件部分的最大大小,但适合 Windows 上的 RAM?
- c# - 在某些圆形边界之外设置 Canvas.SetLeft/Right/Bottom/Top
- python - 是否可以在 pygame 中创建可以删除/弄乱的弹出窗口而不影响主屏幕上显示的内容
- apache-spark - 过滤来自 9000 万用户的数据的最佳架构?
- powershell - PowerShell - 将服务器 LastBootUpTime 转换为 DateTime 格式