android - 即使在设置新适配器后,ViewPager 仍保留 fragment 的实例

标签 android android-fragments android-viewpager fragmentstatepageradapter

我在使用 ViewPagerFragment 的实例时遇到了一些问题。

我有一个包含 4 个 fragment 的 ViewPager(我们称其为父亲),在最后一个 fragment 中我有另一个具有动态 fragment 数量的 ViewPager(并将其称为子 fragment )。我的意思是我根据内存中的对象列表创建子对象。因此,如果列表包含 3 个对象,则 Child 将在其中包含 3 个 fragment 。如果在确定的时刻发生了某些事情并且我得到了一个包含 1 个对象的列表,那么我必须只用 1 个 fragment 更新 Child。这里的重点是每个 Child 的 Fragment 从返回的列表中都有自己的对象,并基于该对象创建。

我将 fragment 列表设置到子 ViewPager 中的代码如下:

@Override
public void setViewPagerChildFragments(List<Fragment> fragments) {
    if (fragments != null) {
        DefaultStateViewPagerAdapter adapter = (DefaultStateViewPagerAdapter) mViewpagerChild.getAdapter();
        if (adapter == null) {
            /* In this case I use getChildFragmentManager() because 
                it's inside the last fragment of the ViewPager Father*/
            adapter = new DefaultStateViewPagerAdapter(getChildFragmentManager(), fragments);
            mViewpagerChild.setAdapter(adapter);
        } else {
            adapter.setFragments(fragments); // Into this method I do notifyDataSetChanged() already
        }
    }
}

请注意,我尝试使用相同的适配器实例来设置 fragment ,然后通知更改(notifyDataSetChanged() 在方法内部)。如果我没有获得适配器的实例,我将创建一个新实例并将其设置为 ViewPager 子项。

问题发生了,例如,当我用 2 个 fragment 设置 ViewPager 子级时,过了一会儿我需要用 1 个 fragment 设置它。 ViewPager 仅显示其中的 1 个 fragment ,但第二个 fragment 仍附加且未被破坏。我知道它是因为我做了一个调用 getChildFragmentManager().getFragments() 的测试,我可以看到应该被销毁的 fragment 仍然存在。

您可能会说这实际上不是问题,因为垃圾收集器 可以删除未使用的 fragment 。但是,例如,如果在某个时刻,我尝试再次将 2 个新 fragment 设置到 ViewPager 子对象中,它会使用未使用的 Fragment 实例而不是创建一个新 fragment ,不幸的是它还使用相同的对象,而不是正确的新对象。

这是我的DefaultStateViewPagerAdapter代码:

public class DefaultStateViewPagerAdapter extends FragmentStatePagerAdapter {

    private ArrayList<Fragment> mFragments;
    private ArrayList<String> mFragmentTitles;

    public DefaultStateViewPagerAdapter(FragmentManager fm) {
        super(fm);
        this.mFragments = new ArrayList<>();
        this.mFragmentTitles = new ArrayList<>();
    }

    public DefaultStateViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.mFragments = (ArrayList<Fragment>) fragments;
    }

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

    @Override
    public int getItemPosition(Object object) {
        int index = mFragments.indexOf(object);
        if (index < 0) {
            index = POSITION_NONE;
        }
        return index;
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitles.get(position);
    }

    public void clearFragments() {
        mFragments.clear();
        mFragmentTitles.clear();
    }

    public void setFragments(List<Fragment> fragments) {
        mFragments = (ArrayList<Fragment>) fragments;
        notifyDataSetChanged();
    }

    public void addFragment(Fragment fragment, String title) {
        mFragments.add(fragment);
        mFragmentTitles.add(title);
    }

}

我已经尝试覆盖 saveState 以避免 ViewPager 使用旧 fragment 的实例,例如:

@Override
public Parcelable saveState() {
    return null;
}

成功了,ViewPager 不再使用旧的引用,但未使用的 Fragment 仍然存在,这会导致内存泄漏。

我不知道为什么 ViewPager 即使在我设置了新的适配器后也没有销毁它的 fragment 。有没有人遇到过这个问题?

最佳答案

我找到了解决方案。

解决方法很简单。我只需要手动将 null 设置为子适配器。这样,ViewPager 就被迫销毁每个 fragment 。

所以我在 Fragment 的父亲的 onDestroyView 中添加了:

@Override
public void onDestroyView() {
    super.onDestroyView();
    mViewpagerChild.removeOnPageChangeListener(mOnPaymentMethodsPageChangeListener);
    mViewpagerChild.setAdapter(null); // <-- This is what I added
}

关于android - 即使在设置新适配器后,ViewPager 仍保留 fragment 的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45761076/

相关文章:

android - 如何在 fragment 中使用 PlaceAutoCompleteFragment 小部件

java - 构造函数参数 "this"从 Activity 但从 Fragment 工作

android - 在 Eclipse 中包含 Android-DirectionalViewPager .jar 时出错

android - 使用 Robolectric 3.2.1 进行 UT 时未绘制 fragment 中的 ViewPager

android - Activity 开始另一个 Activity 。保证第一个 Activity 的 onPause 将在第二个 Activity 的 onResume 之前被调用

Android 布局树,人类可读的解释?

Android - 如何将数据从 Activity 传递到 fragment ?

android - 将内容列表获取到 Fragment Adapter (viewpager)

java - 我通过 Intent 上传的文本和网址对于 Twitter 来说太长

android - NotificationListenerService 中的 OnListenerCONnected 未被调用