动态更新ViewPager中的Fragment(替换Fragment)
1.最近做需求,遇到一个问题,一个Fragment中包含了一个ViewPager,viewPager中包含一adapter ,adapter中包含了4个Fragment。想要动态替换第3个Fragment由A Fragment--》B Fragment。如图:
2. 原本以为很简单的事,分分钟就能搞定,但是更新了list<Fragment> 数据源,notifyDataSetChanged()后,页面没有被替换,邪门啊。
3.上网一通乱查,发现一个说法:重写getItemPosition()方法返回POSITION_NONE 进行刷新。于是乎,查了下源码,大致刷新的过程,如图:
4.流程知道了,具体怎么实现呢。从无到有是最难的,还是参考下系统类吧:FragmentPagerAdapter ,把它重写。见代码
public class TabFragmentAdapter extends PagerAdapter { private static final String TAG = "FragmentPagerAdapter"; private static final boolean DEBUG = false; private FragmentManager mFragmentManager; private FragmentTransaction mCurTransaction = null; private Fragment mCurrentPrimaryItem = null; private boolean isRefesh = false; ArrayList<Fragment> list = new ArrayList<>(); //刷新对象的接口 public interface RefeshFragment{ } public boolean isRefesh(Object object) { if (isRefesh && (object instanceof RefeshFragment)) { return true; } else { return false; } } public void setRefesh(boolean t) { isRefesh = t; } public TabFragmentAdapter(FragmentManager fm) { mFragmentManager = fm; } public void setFragments(ArrayList fragments) { if (this.list != null) { this.list = fragments; } } public Fragment getItem(int position) { return list.get(position); } @Override public int getCount() { return list == null ? 0 : list.size(); } @SuppressWarnings("ReferenceEquality") @Override public Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null && !(isRefesh(fragment))) { if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } if (isRefesh(fragment)) { isRefesh = false; } return fragment; } @Override public void destroyItem(ViewGroup container, int position, Object object) { if (mCurTransaction == null || isRefesh(object)) {//避免缓存指令的干扰 每次使用新的 BackStackRecord 对象 mCurTransaction = mFragmentManager.beginTransaction(); } if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object + " v=" + ((Fragment) object).getView()); if (isRefesh(object)) { mCurTransaction.remove((Fragment) object); } else { mCurTransaction.detach((Fragment) object); } } @SuppressWarnings("ReferenceEquality") @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { Fragment fragment = (Fragment) object; if (fragment != mCurrentPrimaryItem) { if (mCurrentPrimaryItem != null) { mCurrentPrimaryItem.setMenuVisibility(false); mCurrentPrimaryItem.setUserVisibleHint(false); } if (fragment != null) { fragment.setMenuVisibility(true); fragment.setUserVisibleHint(true); } mCurrentPrimaryItem = fragment; } } @Override public void finishUpdate(ViewGroup container) { if (mCurTransaction != null) { mCurTransaction.commitAllowingStateLoss(); mCurTransaction = null; } } @Override public boolean isViewFromObject(View view, Object object) { return ((Fragment) object).getView() == view; } @Override public Parcelable saveState() { return null; } @Override public void restoreState(Parcelable state, ClassLoader loader) { } public long getItemId(int position) { return position; } private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; } @Override public int getItemPosition(Object object) { if (isRefesh(object)) {//是否进行销毁 return POSITION_NONE; } else { return POSITION_UNCHANGED; } } }
5.说明:
a.你要替换的Fragment需要先实现空接口RefeshFragmnet,用来表明你是需要被替换的。
b.调用时
mFragmentList.set(FRAGMENT_STOCKS,new StocksFragment());//替换数据源 adapter.setRefesh(true);//设置刷新标识 adapter.notifyDataSetChanged();//通知adapter刷新
6.小结:其实adapter的源码挺简单的,viewPager比较复杂。只要有耐心,跟着源码debug,为之,则难者亦易矣。上边的代码要是有不懂的地方可以在下方留言或者debug一下