Android popBackStack后未还原ViewPager中的片段 问题

Android popBackStack后未还原ViewPager中的片段 问题,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,从另一个片段返回后,片段不会重新附着到其宿主ViewPager 处境 承载片段的一个活动,其布局包含一个ViewPager(PageListFragment,在下面的示例中)。ViewPager由FragmentStateViewPagerAdapter填充。位于寻呼机内的单个片段(PageFragment,在下面的示例中)可以打开包含一组新页面的子页面列表 行为 只要不按下后退按钮,所有操作都正常。一旦用户关闭其中一个子页面列表,将重新创建上一个列表,但不包含以前显示的页面。浏览父页面列表上的

从另一个片段返回后,片段不会重新附着到其宿主ViewPager

处境 承载片段的一个活动,其布局包含一个ViewPager(
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)
    }
}