FragmentPagerAdapter getItem不被调用


123

我无法在FragmentPagerAdapter中重用片段。使用destroyItem()方法,它正在删除片段,但仍然不会再次调用getItem()。.只有2-3张图像,所以我使用FragmentPagerAdapter而不是FragmentStatePagerAdapter。

public class ExamplePagerAdapter extends FragmentPagerAdapter {

    ArrayList < String > urls;
    int size = 0;
    public ExamplePagerAdapter(FragmentManager fm, ArrayList < String > res) {
        super(fm);
        urls = res;
        size = urls.size();
    }

    @Override
    public int getCount() {
        if (urls == null) {
            return 0;
        } else {
            return size;
        }

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = new FloorPlanFragment();
        Bundle b = new Bundle();
        b.putInt("p", position);
        b.putString("image", urls.get(position));
        Log.i("image", "" + urls.get(position));
        fragment.setArguments(b);
        return fragment;
    }
}

在FragmentActivity中

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 

3
你有什么特别的理由destroyItem()吗?那是没有必要的。
CommonsWare's

再次使用FragmentStatePagerAdapter进行初始化,当您覆盖它时也调用super.destroyItem(container,position,object);
faiziii

Answers:


306

吻答案:

只需使用FragmentStatePagerAdapter而不是FragmentPagerAdapter即可

我得到了答案。首先,我想删除此问题,因为我犯了一个非常愚蠢的错误,但是此答案将帮助遇到相同问题(而不是FragmentPagerAdapter使用)的人FragmentStatePagerAdapter

正如@BlackHatSamurai在评论中提到的:

起作用的原因是因为FragmentStatePagerAdapter销毁为未被使用的片段。FragmentPagerAdapter才不是。


非常感谢。您的回答对我很有帮助。
Priya 2013年

1
不想成为另一个“我也是”!发布,但是>。<感谢您不要删除此问题。
Paul Ruiz 2013年

34
之所以起作用,是因为FragmentStatePagerAdapter会作为未使用的Fragment销毁。FragmentPagerAdapter没有。
BlackHatSamurai

3
仅供将来参考,供那些在寻找特定问题时发现的人参考;在FragmentPagerAdapter和FragmentStatePagerAdapter上阅读。由于某种原因,它们的行为有所不同,您的特定用途可能需要一个。
克里斯·斯图尔特

2
@najibputhawala我使用了FragmentStatePagerAdapter,但仍然面临同样的问题。getItem()未调用
sam_k 2014年

168

使用a FragmentStatePagerAdapter并不能完全解决我的问题,这是一个相似的问题,onCreateView在视图分页器中未调用子片段。我实际上是将我的FragmentPagerAdapter内部嵌套在另一个内部,Fragment因此FragmentManager它们在所有这些内部都共享,因此保留了旧片段的实例。解决方法是改为将实例送入我的主机片段中getChildFragmentManager的构造函数FragmentPagerAdapter。就像是...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

getChildFragmentManager()方法可通过片段访问,这对我有用,因为它FragmentManager专门为需要嵌套片段的情况返回该片段的私有数据。我希望这可以帮助可能遇到与我相同的问题的人!

  • 但是请记住,getChildFragmentManager()至少要使用您的最低API版本17 (4.2),否则可能会给您造成麻烦。当然,如果您使用的是支持库v4中的片段,则应该可以。

25
这是正确的答案。问题是由于嵌套在其他片段中的片段应使用getChildrenFragmentManager()而不是getFragmentManager()。
shihpeng

非常感谢,我花了我一整天才找到答案!
Shpongoloid

我同意@shihpeng。这应该是正确的答案。
雷蒙德·卢坎塔

这对我来说是一个修复。非常感谢您提交答案
user3734429 2015年

文档应该真正在流程中加以说明。在片段中加载ViewPager是非常现实的。感谢您发布此答案。
工作

7

覆写 long getItemId (int position)

FragmentPagerAdapter缓存使用创建的片段getItem。即使notifyDataSetChanged() getItem没有打电话,我也面临着同样的问题。

这实际上是一个功能,而不是错误。您需要重写,getItemId以便可以正确地重用您的片段。由于您正在去除碎片,因此您的位置正在改变。如文档中所述:

long getItemId (int position)

返回给定位置的商品的唯一标识符。

默认实现返回给定位置。如果项的位置可以更改,则子类应重写此方法。

只需为每个片段提供唯一的ID,就可以完成。

使用a FragementStatePagerAdapter或return POSITION_NONEin int getItemPosition (Object object)是错误的。您将不会获得任何缓存。


这是正确的答案。我必须为getItemIdAND中的片段提供不同的ID,如果要删除片段,请调整getItemPosition以返回POSITION_NONE。我有一个枚举标志。之后getItem将被调用。
MuratKaragöz

谢谢@MuratKaragöz的+50 :)
vedant

5

我做了@kanika和@ Jraco11所发布的内容,但仍然有问题。

因此,经过大量更改,我发现了一个对我有用的文件,并将下一个代码添加到FragmentPagerAdapter中:

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

根据我所读的内容,getItemPosition用于通知ViewPager是否刷新项目,并在可见位置的项目未更改的情况下避免更新。


2

有两种不同的方案:1.)每个寻呼机都具有相同的布局:在这种情况下,最好通过PagerAdapter扩展自定义适配器并返回单个布局,这样会更好。

2.)每个分页器都有不同的布局:在这种情况下,最好通过FragmentStatePagerAdapter扩展自定义适配器并为每个分页器返回不同的fragmet。


2

方法getItem()仅用于创建新项目。创建后,将不会调用此方法。如果需要获取适配器使用的货币项目,请使用以下方法:

pagerAdapter.instantiateItem(viewPager, TAB_POS)

0

我发现在选项卡布局上设置一个侦听器可以阻止此调用,这可能是因为它们仅具有一个侦听器的空间,tabLayout.setOnTabSelectedListener而不是一组侦听器的空间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.