PagerAdapter使用notifyDataSetChanged 但是有时数据并为改变的原因。
class ViewAdapter extends PagerAdapter{ private List<View> list; ViewAdapter(List<View> list){ this.list = list; } //返回view视图的数目 @Override public int getCount() { return list.size(); } // 当要显示的视图可以进行缓存的时候,会调用这个方法进行显示视图的初始化, // 我们将要显示的View加入到ViewGroup中,然后作为返回值返回即可 @Override public Object instantiateItem(ViewGroup container, int position) { return super.instantiateItem(container, position); } //PagerAdapter只缓存一定的视图,如果滑动的视图超出了缓存的范围,就会调用这个方法,将视图销毁 @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); } // 来判断显示的是否是同视图(对象),这里我们将两个参数相比较返回即可 @Override public boolean isViewFromObject(View view, Object object) { return false; } }
当传入listView时 视图调用方法初始化,
之后想要改变viewPager中的视图,即需要改变传入的listView值时,
之后再调用 adapter.notiyDatasetChange()。 改变所有的数据可以在实现PagerAdapter时,
写一个setList( ? extend List<T>)方法 中带有notiyDatasetChange() 方法,这样在外部改变值的时候直接改变listView即可。
例如:
public void setList(List<View>list) { this.list = list; notifyDataSetChanged(); }
但实际上,传入不同的listView 且调用了notifyDataSetChanged方法时,视图有时并未改变。
这是为什么呢?
我们来看一下关于notifyDataSetChange()的源码:
/** * This method should be called by the application if the data backing this adapter has changed * and associated views should update. */ public void notifyDataSetChanged() { synchronized (this) { if (mViewPagerObserver != null) { mViewPagerObserver.onChanged(); } } mObservable.notifyChanged(); }
private DataSetObserver mViewPagerObserver;
DataSetObserver 这个数据观察者明显是从ViewPager中去实现的
然后我去ViewPager中找了找这个mViewPagerObserver
private class PagerObserver extends DataSetObserver { PagerObserver() { } @Override public void onChanged() { dataSetChanged(); } @Override public void onInvalidated() { dataSetChanged(); } }
void setViewPagerObserver(DataSetObserver observer) { synchronized (this) { mViewPagerObserver = observer; } }
所以可以发现调用notifyDataSetChanged 时,会触发ViewPager的 PagerObserver 的
dataSetChanged方法而dataSetChanged的源码描述如下
dataSetChanged方法而dataSetChanged的源码描述如下
void dataSetChanged() { // This method only gets called if our observer is attached, so mAdapter is non-null. final int adapterCount = mAdapter.getCount(); mExpectedAdapterCount = adapterCount; boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 && mItems.size() < adapterCount; int newCurrItem = mCurItem; boolean isUpdating = false; for (int i = 0; i < mItems.size(); i++) { final ItemInfo ii = mItems.get(i);
//通过getItemPosition(Object object)的返回值来执行的后续操作, final int newPos = mAdapter.getItemPosition(ii.object); //可以发现当返回值为POSITION_UNCHANGED 直接跳出循环 if (newPos == PagerAdapter.POSITION_UNCHANGED) { continue; } //而为 PagerAdapter.POSITION_NONE 时,才继续执行后续操作 if (newPos == PagerAdapter.POSITION_NONE) { mItems.remove(i); i--; if (!isUpdating) { mAdapter.startUpdate(this); isUpdating = true; } mAdapter.destroyItem(this, ii.position, ii.object); needPopulate = true; if (mCurItem == ii.position) { // Keep the current item in the valid range newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1)); needPopulate = true; } continue; } if (ii.position != newPos) { if (ii.position == mCurItem) { // Our current item changed position. Follow it. newCurrItem = newPos; } ii.position = newPos; needPopulate = true; } } if (isUpdating) { mAdapter.finishUpdate(this); } Collections.sort(mItems, COMPARATOR); if (needPopulate) { // Reset our known page widths; populate will recompute them. final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (!lp.isDecor) { lp.widthFactor = 0.f; } } setCurrentItemInternal(newCurrItem, false, true); requestLayout(); } }
可以看到 mAdapter.getItemPosition(ii.object); 的返回值决定了后续的操作,
而默认的PagerAdapter的实现类 getItemPosition(Object object)返回值为
PagerAdapter.POSITION_UNCHANGED;
因此当未重写getItemPosition(Object object )方法时,调用 notiy
dataSetChanged()
方法
,
他/她并未执行我们想要得到接过。
因此需要我们将getItemPosition( Object object ) 重写 将返回值写成 PagerAdapter.POSITION_NONE 它才会调用销毁视图的方法,之后得到我们想要的结果。
//为了内部视图变换 @Override public int getItemPosition(Object object) { return POSITION_NONE; }
至此,再次运行程序即可得到你想要的接过。