PagerAdapter使用notifyDataSetChanged 但是视图并为改变的原因。


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;
    }
}


一个viewPager 的Adapter必须实现的四个方法。
当传入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的源码描述如下

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;
}

至此,再次运行程序即可得到你想要的接过。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值