Android popBackStack后未还原ViewPager中的片段 问题
从另一个片段返回后,片段不会重新附着到其宿主ViewPager 处境 承载片段的一个活动,其布局包含一个ViewPager(Android popBackStack后未还原ViewPager中的片段 问题,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,从另一个片段返回后,片段不会重新附着到其宿主ViewPager 处境 承载片段的一个活动,其布局包含一个ViewPager(PageListFragment,在下面的示例中)。ViewPager由FragmentStateViewPagerAdapter填充。位于寻呼机内的单个片段(PageFragment,在下面的示例中)可以打开包含一组新页面的子页面列表 行为 只要不按下后退按钮,所有操作都正常。一旦用户关闭其中一个子页面列表,将重新创建上一个列表,但不包含以前显示的页面。浏览父页面列表上的
PageListFragment
,在下面的示例中)。ViewPager由FragmentStateViewPagerAdapter填充。位于寻呼机内的单个片段(PageFragment
,在下面的示例中)可以打开包含一组新页面的子页面列表
行为
只要不按下后退按钮,所有操作都正常。一旦用户关闭其中一个子页面列表,将重新创建上一个列表,但不包含以前显示的页面。浏览父页面列表上的其他页面仍然有效
代码
可以在以下站点上找到示例应用程序:
经过长时间的调查,结果证明这是碎片管理器的问题 当使用类似于片段事务上方的构造将片段重新附加到页面列表时,将自动放弃该事务。基本上是同一个问题导致了
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
尝试更改FragmentPager内的片段时
对于这个错误的问题,同样的解决方案也适用于这里。构造FragmentStatePagerAdapter时,请提供正确的子片段管理器
而不是
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString));
做
另请参见:Paul没有提到的是,如果您使用getChildFragmentManager,那么您将遇到“按下后的空白屏幕”问题 在我的案例中,层次结构是:
main活动
->main片段
->表格布局
+查看页面
->会计片段
+储蓄片段
+投资片段
等
我遇到的问题是,我无法使用childFragmentManager
,原因是单击项目Account view
(位于ViewPager
的片段中)需要替换main片段,即整个屏幕
使用MainFragment
s主机Fragment
即通过getFragmentManager()
启用了替换,但在弹出后堆栈时,我出现了以下屏幕:
通过查看布局检查器,ViewPager
为空,这一点也很明显
显然,在查看已还原的片段时,您会注意到它们的视图已还原,但与弹出状态的层次结构不匹配。为了使影响最小,并且不强制重新创建片段
s,我重新编写了FragmentStatePagerAdapter
,并做了以下更改:
我复制了FragmentStatePagerAdapter
的整个代码并进行了更改
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
...
}
与
通过这种方式,我可以有效地确保恢复的片段
s重新连接到查看页面
删除所有页面片段,以便以后可以重新添加它们
当您返回到viewpager屏幕时,页面片段不会附加,因为FragmentStatePagerAdapter没有重新连接它们。作为一种解决方法,在调用popbackstack()后删除viewpager中的所有片段,这将允许通过初始代码重新添加这些片段
[此示例是用Kotlin编写的]
只需提及:简单地覆盖public int getItemPosition(Object Object)
Yesss是不起作用的!getChildFragmentManager()是我的头撞在墙上想弄明白的!好东西@保罗,你的帖子帮助我挽救了三年后的日子。非常感谢。天哪,两周后终于成功了!,谢谢@NitishChopra getChildFragmentManager()可以在扩展碎片的类的同一个非静态上下文中调用。谢谢,这(某种)是有效的。但是现在onSaveInstanceState在单个片段中没有被调用(在您的例子中是PageFragment)。有解决方法吗?在这个问题上有很多问题,他们都建议我们使用子片段管理器,我就是这么做的。但是我的FragmentStatePagerAdapter
在返回到时不会重新连接其片段,导致一个空白屏幕。哈哈+1、找到了!我在这里问了同样的问题@Mahesh,我回复了你的帖子。希望它能帮助别人!!
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getFragmentManager(),mParentString));
viewPager.setAdapter(new SimpleFragmentStatePagerAdapter(getChildFragmentManager(),mParentString));
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
...
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
mCurTransaction.detach(f);
mCurTransaction.attach(f);
return f;
}
}
...
}
//Clear all fragments from the adapter before they are re-added.
for (i: Int in 0 until adapter.count) {
val item = childFragmentManager.findFragmentByTag("f$i")
if (item != null) {
adapter.destroyItem(container!!, i, item)
}
}