【问题标题】:Replace a fragment within a Viewpager(notifyDataSetChanged does not work)替换 Viewpager 中的片段(notifyDataSetChanged 不起作用)
【发布时间】:2015-06-30 10:17:26
【问题描述】:

我的 MainActivity 包含一个 viewPager。

在 MainActivity.java 中,我为 viewpager 设置了适配器。该适配器扩展了 FragmentStatePagerAdapter。我要替换的片段是 相机片段。因此,当用户点击切换摄像头按钮时,我现在想显示摄像头片段,这次要打开前置摄像头。

单击切换相机按钮时,我从传递给自定义适配器的片段数组列表中删除片段。我添加新片段并调用 notifydatasetchanged。但是,这不会导致添加新片段。如何在支持我的自定义片段状态寻呼机适配器的 viewpager 中实现片段的动态替换? 代码:

mainPageFragments = new ArrayList<>();
mainPageFragments.add(new ResultsFragment_());
mainPageFragments.add(DemoCameraFragment_.newInstance(false));
pagerAdapter = new MainViewPagerAdapter(getSupportFragmentManager(),mainPageFragments);

要替换片段:在收到我所做的相关事件时,

mainPageFragments.remove(1);
    if (event.getCameraState().equals(CameraSwitchButton.CameraTypeEnum.BACK)) {
        mainPageFragments.add(DemoCameraFragment.newInstance(false));
    } else {
        mainPageFragments.add(DemoCameraFragment.newInstance(true));

    }
    // Not Working...
    pagerAdapter.notifyDataSetChanged();

适配器代码:

public class MainViewPagerAdapter extends FragmentStatePagerAdapter {

ArrayList<Fragment> fragmentsArray;

public MainViewPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragmentsArray) {
    super(fm);
    this.fragmentsArray = fragmentsArray;
}

@Override
public Fragment getItem(int position) {
    return fragmentsArray.get(position);
}

@Override
public int getCount() {
    return fragmentsArray.size();
}

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

【问题讨论】:

  • 发布一些你所做的代码
  • @Mano。关于如何更新/替换片段的任何想法?显然我错过了一些东西。我不想重置适配器。这似乎是一个昂贵的操作(如果页面/片段的数量增加。另外,我只需要替换一个片段,所以重新实例化每个其他片段没有任何意义。
  • 请发布 MainViewPagerAdapter 的代码。
  • @Okas。用 MainViewPagerAdapter 更新它。

标签: android android-fragments android-viewpager notifydatasetchanged fragmentstatepageradapter


【解决方案1】:

您的 MainViewPagerAdapter.getItemPosition 是您的问题的原因。

默认实现总是返回 POSITION_UNCHANGED。要让寻呼机删除您的片段,您必须为已删除的片段返回 PagerAdapter.POSITION_NONE。

此外,您当前的设计与 FragmentStatePagerAdapter 的想法相矛盾。来自 FragmentStatePagerAdapter documentation:“这个版本的分页器在有大量页面时更有用,更像列表视图。当页面对用户不可见时,它们的整个片段可能会被销毁,只保留该片段的已保存状态。与 FragmentPagerAdapter 相比,这允许分页器保留与每个访问页面相关联的内存少得多,但代价是在页面之间切换时可能会产生更多开销。"

您当前的实现将所有片段保存在一个数组中,因此破坏了这种机制。正确的实现是在 MainViewPagerAdapter.getItem 方法中创建片段,并让适配器根据需要处理片段生命周期。

【讨论】:

  • 即使我以这种方式实现适配器,我该如何替换片段?我已经阅读了 getItemPosition 的默认实现。我使用 FragmentStatePageAdapter 的原因是 viewpager 中的页面数量很有可能会增加。我仍然无法弄清楚我应该在 getItemPosition 方法中做什么来解决我的问题。谢谢。
  • 您必须单独跟踪要保留哪些片段以及要删除哪些片段。然后,当某些事情发生变化时,您必须调用 notifyDataSetChanged()。然后寻呼机将调用您的适配器 getItemPosition 方法。您必须为要删除的内容返回 POSITION_NONE,然后寻呼机将为您删除这些内容。
  • 谢谢@Okas。我根据您的帖子进行了更改,并在下面发布了答案。
【解决方案2】:

感谢@Okas。我在 FragmentStatePagerAdapter 子类中对 getItemPosition 进行了以下更改。

@Override
 public int getItemPosition(Object object) {
    if (object instanceof DemoCameraFragment_)
        return POSITION_NONE;
    return super.getItemPosition(object);
}

我在两个片段的 OnCreate 中添加了日志,以确认它们是否被重新创建。根据我的要求,只重新创建了第二个片段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多