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)