android 导航回FragmentPagerAdapter ->片段为空

vq8itlhq  于 2022-12-25  发布在  Android
关注(0)|答案(5)|浏览(107)

我有一个Fragment(我称之为pagerFragment),它被添加到backstack中并且是可见的,它包含一个viewPager和一个FragmentPagerAdapterFragmentPagerAdapter包含(比方说)两个fragment:A和B
第一次添加片段效果很好。
片段A有一个按钮,一旦被点击,就会将一个片段(C)添加到backstack。
问题是这样的:如果添加片段(C),然后单击Back,则pagerAdapter为空,且看不到其中任何片段。
如果我使用一个hack,并销毁pagerFragment s onDestroyView()中的子片段(A和B),这就解决了问题,尽管我不想不使用这个hack。
你知道是什么问题吗?

62o28rlo

62o28rlo1#

我也遇到了同样的问题。我的解决办法很简单:
在onCreateView中,我有:

// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity()
    .getSupportFragmentManager());

其中,SectionPageAdapter类似于以下内容:

class SectionsPagerAdapter extends FragmentPagerAdapter {
...
}

将getSupportFragmentManager更改为

mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());

它开始工作了!

vawmfj5a

vawmfj5a2#

由于ViewPager位于PagerFragment内部,因此听起来像是使用了嵌套片段。是否已将getChildFragmentManager()传递给FragmentPagerAdapter的构造函数?如果未传递,则应传递。
我不认为你需要一个FragmentStatePagerAdapter,但我会给它一个机会,因为它处理保存和恢复片段状态.事实上,你的onDestroyView()破解工作让我认为你可能需要一个FragmentStatePagerAdapter.
这也可能与FragmentPagerAdapter添加片段的方式有关。FragmentPagerAdapter不会将片段添加到backstack。想象一下,如果你在ViewPager中添加了10多个页面,用户在其中滑动。用户需要点击11次才能退出应用程序。
也可能和这个帖子有关:Nested Fragments and The Back Stack.
我也不确定你要把C片段加到什么地方。你是把它加到和ViewPager相同的容器里吗?
好吧,至少你有几个选项可以研究。在这种情况下,我喜欢调试Android SDK源代码,看看是什么导致了这种行为。我建议抓住AOSP source,并添加frameworks/support和frameworks/base作为SDK源代码。这是了解正在发生的事情并避免在事情正常工作之前进行随机更改的唯一真正方法。

mlnl4t2r

mlnl4t2r3#

使用getChildFragmentManager()代替getSupportFragmentManager(),它会工作得很好。

cgh8pdjw

cgh8pdjw4#

我在我们的项目中也遇到了这个问题,根本原因是FragmentPagerAdapter的工作方式:
FragmentPagerAdapter只是从其视图中分离他当前不需要的片段,但不从其FragmentManager中移除该片段。当他想要再次显示该片段时,他使用从ViewPager的视图id和适配器getItemId返回的id创建的标记来查看FragmentManager是否仍然包含该片段(position)调用。如果他找到了一个片段,他就在FragmentManager的更新事务中调度一个片段到它的视图的附加。只有当他没有找到一个片段时,他才使用适配器getItem(position)调用创建一个新的片段!
包含具有FragmentPagerAdapter的ViewPager的Fragment的问题在于,将包含Fragment的FragmentManager放入后台堆栈时,FragmentManager的内容永远不会清除。如果包含Fragment从后台堆栈返回,它将创建新视图,但FragmentManager仍包含附加到旧视图的片段,并且现有片段的附加不再起作用。
解决这个问题最简单的方法是避免嵌套片段。:)
第二个最简单的方法是,正如在其他文章中提到的,使用ChildFragmentManager作为FragmentPagerAdapter,因为它在容器片段的生命周期中会得到正确的更新。
由于有些项目(如我目前的项目)两种选择都不可行,我在这里发布了一个解决方案,它可以使用任意的FragmentManager,方法是使用子片段的hashCode作为该位置片段的项id,其代价是在适配器中存储所有位置的所有片段。

public class MyPagerAdapter extends FragmentPagerAdapter {

private static int COUNT = ...;
private final FragmentManager fragmentManager;
private Fragment[] subFragments = new Fragment[COUNT];
private FragmentTransaction cleanupTransaction;

public MyPagerAdapter(FragmentManager fragmentManager) {
    super(fragmentManager);
    this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
    return getSubFragmentAtPosition(position);
}

@Override
public int getCount() {
    return COUNT;
}

@Override
public long getItemId(int position) {
    return getSubFragmentAtPosition(position).hashCode();
}

//The next three methods are needed to remove fragments no longer used from the fragment manager
@Override
public void startUpdate(ViewGroup container) {
    super.startUpdate(container);
    cleanupTransaction = fragmentManager.beginTransaction();
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    cleanupTransaction.remove((Fragment) object);
}

@Override
public void finishUpdate(ViewGroup container) {
    super.finishUpdate(container);
    cleanupTransaction.commit();
}

private Fragment getSubFragmentAtPosition(int position){
    if (subFragments[position] == null){
        subFragments[position] = ...;
    }
    return subFragments[position];
}

}

cunj1qz1

cunj1qz15#

    • 我遇到了同样的问题,**只是一次设置两次适配器,仅此而已。

示例代码:

private fun displayImg(photo1:String, photo2:String){
    val pager:ViewPager = v?.findViewById(R.id.ProductImgPager)!!
    val arr = ArrayList<String>()
    arr.add(photo1)
    arr.add(photo2)
    pager.adapter = AdapterImageView(fm, arr ,arr.size)
    pager.adapter = AdapterImageView(fm, arr ,arr.size)

}

相关问题