我们知道ViewPager设置PagerAdapter之后通过notifyDataSetChanged方法也可以更新ViewPager,那么这是怎么实现的呢?答案是观察者模式。
我们来看一下关于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中去实现的
private class PagerObserver extends DataSetObserver {
PagerObserver() {
}
@Override
public void onChanged() {
dataSetChanged();
}
@Override
public void onInvalidated() {
dataSetChanged();
}
}
可以发现调用notifyDataSetChanged 时,会触发ViewPager的 PagerObserver 的
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; }