Android ViewPager如何动态增删Fragment,解决ViewPager缓存问题

开发 一个 Android App, 基本离不开ViewPager+Fragment。有时候我们需要在Fragment中动态增加或者删除一个Fragment,比如登陆状态和未登录、会员和非会员状态下ViewPager 显示的Fragment 数量是不一致的,而如果我们只改变List<Fragment>  中的数据源,然后调用FragmentPagerAdapter和FragmentPagerStateAdapter 的NotifyDataChanged,结果很失望,没有达到想要的结果,这是因为ViewPager的缓存问题。

网上有给出以下代码,这段代码有什么问题?问题就是ViewPager 中所有的Fragment 都将会重新创建,比如某个Fragment 中有列表数据,在浏览了几页的数据情况下(分页),Fragment 突然被重建,这个就很糟糕,我们只想动态增删指定Fragment,不想已经显示的Fragment 有任何改变,显然下面这段代码是不合适的。

public int getItemPosition(Object object) {return PagerAdapter.POSITION_NONE;}
自定义一个支持动态增删Fragment的Adapter

public class FragmentAddDelPagerAdapter extends FragmentStatePagerAdapter {    private FragmentManager mFragmentManager;    private List<Fragment> mFragments = new ArrayList<>();    private List<String> mTitles = new ArrayList<>();

    public FragmentAddDelPagerAdapter(FragmentManager fm) {        super(fm);        this.mFragmentManager = fm;    }

    public void bindFragment(List<Fragment> fragments,List<String> titles) {        if (EmptyUtils.isEmpty(fragments)) return;        this.mFragments.clear();        this.mFragments.addAll(fragments);        mTitles.clear();        mTitles.addAll(titles);        notifyDataSetChanged();    }

    /**     * 在notifyDataSetChanged 先改变TabLayout,     *   mPagerAdapter.bindFragment(fragments, titles, new FragmentAddDelPagerAdapter.OnBeforeNotifyDataChangedListener() {     *                 @Override     *                 public void onBeforeNotify() {     *                     tabLayout.notifyDataSetChanged();     *                 }     *     *             });     */    public void bindFragment(List<Fragment> fragments,List<String> titles,OnBeforeNotifyDataChangedListener listener) {        if (EmptyUtils.isEmpty(fragments)) return;        this.mFragments.clear();        this.mFragments.addAll(fragments);        mTitles.clear();        mTitles.addAll(titles);        if (listener!=null)listener.onBeforeNotify();        notifyDataSetChanged();    }

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

    @Nullable    @Override    public CharSequence getPageTitle(int position) {        return EmptyUtils.isNotEmpty(mTitles)?mTitles.get(position):"";    }

    @Override    public int getCount() {        return EmptyUtils.isNotEmpty(mFragments)? mFragments.size():0;    }

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

    @Override    public int getItemPosition(Object object) {        if (!((Fragment) object).isAdded() || !mFragments.contains(object)) {            return PagerAdapter.POSITION_NONE;        }        return mFragments.indexOf(object);    }

    @Override    public Object instantiateItem(ViewGroup container, int position) {

        Fragment instantiateItem = ((Fragment) super.instantiateItem(container, position));        Fragment item = mFragments.get(position);        if (instantiateItem == item) {            return instantiateItem;        } else {            //如果集合中对应下标的fragment和fragmentManager中的对应下标的fragment对象不一致,那么就是新添加的,所以自己add进入;这里为什么不直接调用super方法呢,因为fragment的mIndex搞的鬼,以后有机会再补一补。            mFragmentManager.beginTransaction().add(container.getId(), item).commitNowAllowingStateLoss();            return item;        }    }

    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        Fragment fragment = (Fragment) object;        //如果getItemPosition中的值为PagerAdapter.POSITION_NONE,就执行该方法。        if (mFragments.contains(fragment)) {            super.destroyItem(container, position, fragment);            return;        }        //自己执行移除。因为mFragments在删除的时候就把某个fragment对象移除了,所以一般都得自己移除在fragmentManager中的该对象。        mFragmentManager.beginTransaction().remove(fragment).commitNowAllowingStateLoss();    }

    public interface OnBeforeNotifyDataChangedListener{        void onBeforeNotify();    }

    /** * 在notifyDataSetChanged 先改变TabLayout, *   mPagerAdapter.bindFragment(fragments, titles, new FragmentAddDelPagerAdapter.OnBeforeNotifyDataChangedListener() { *                 @Override *                 public void onBeforeNotify() { *                     tabLayout.notifyDataSetChanged(); *                 } * *             }); */
(0)

相关推荐