ViewPager的addOnPageChangeListener和setOnPageChangeListener的区别,ViewPager改变数据后IndexOutOfBoundsException

我的ViewPager数据改变后,在切换界面刷新数据时:OnPageChangeListener中的数据IndexOutOfBoundsException,我们来看源码探一下究竟;

代码时这样写的:

vpLoveCar.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        PreferenceUtil.set("OWNERCARVIN",carList.get(position).getVin_code());//记录当前索引,下拉刷新时更新该辆车;再次进入时显示该辆车;
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

各种使用都没有问题,但是当carList的集合长度变化时(size变大后),我再去切换就会崩溃,这个问题足足影响了一个星期,我一直以为是数据操作的问题;直到今天我看了addOnPageChangeListener的源码。。。。。。

ViewPager的addOnPageChangeListener的源码:

private List<OnPageChangeListener> mOnPageChangeListeners;
private OnPageChangeListener mOnPageChangeListener;

/**
 * Add a listener that will be invoked whenever the page changes or is incrementally
 * scrolled. See {@link OnPageChangeListener}.
 *
 * <p>Components that add a listener should take care to remove it when finished.
 * Other components that take ownership of a view may call {@link #clearOnPageChangeListeners()}
 * to remove all attached listeners.</p>
 *
 * @param listener listener to add
 */
public void addOnPageChangeListener(@NonNull OnPageChangeListener listener) {
    if (mOnPageChangeListeners == null) {
        mOnPageChangeListeners = new ArrayList<>();
    }
    mOnPageChangeListeners.add(listener);
}

ViewPager的setOnPageChangeListener的源码:

/**
 * Set a listener that will be invoked whenever the page changes or is incrementally
 * scrolled. See {@link OnPageChangeListener}.
 *
 * @param listener Listener to set
 *
 * @deprecated Use {@link #addOnPageChangeListener(OnPageChangeListener)}
 * and {@link #removeOnPageChangeListener(OnPageChangeListener)} instead.
 */
@Deprecated
public void setOnPageChangeListener(OnPageChangeListener listener) {
    mOnPageChangeListener = listener;
}

由源码可知:addOnPageChangeListener这个方法,每调用一次都会添加一个OnPageChangeListener的监听,ViewPager会把这些监听存在一个List的集合中;所以我每次add一个监听,就会增加一个OnPageChangeListener,里面的数据也会有不同;会导致你有多个OnPageChangeListener,但是每个回调里面的position却是同样的,它去你集合长度小的那个里面OnPageChangeListener去获取数据,所以会下标越界异常;

源码提示让你在添加时去清空之前的OnPageChangeListener:

/**
 * Remove all listeners that are notified of any changes in scroll state or position.
 */
public void clearOnPageChangeListeners() {
    if (mOnPageChangeListeners != null) {
        mOnPageChangeListeners.clear();
    }
}

   而setOnPageChangeListener这个方法,每调用一次都会新设置一个OnPageChangeListener的监听,ViewPager会替换你之前的监听; 用这个方法的话数据每次都是最新的,所以不会下表越界异常;

/**
 * Remove a listener that was previously added via
 * {@link #addOnPageChangeListener(OnPageChangeListener)}.
 *
 * @param listener listener to remove
 */
public void removeOnPageChangeListener(@NonNull OnPageChangeListener listener) {
    if (mOnPageChangeListeners != null) {
        mOnPageChangeListeners.remove(listener);
    }
}

我最后的解决方式,有两种:

1、先清空在添加监听

vpLoveCar.clearOnPageChangeListeners();
vpLoveCar.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        PreferenceUtil.set("OWNERCARVIN",carList.get(position).getVin_code());//记录当前索引,下拉刷新时更新该辆车;再次进入时显示该辆车;
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

2、设置监听

vpLoveCar.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        PreferenceUtil.set("OWNERCARVIN",carList.get(position).getVin_code());//记录当前索引,下拉刷新时更新该辆车;再次进入时显示该辆车;
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

收获不小,我之前在使用这些方法没有出问题的时候,我一直认为addOnPageChangeListener和setOnPageChangeListener是一样的,知道今天改变数据后会下标越界异常;多去看一下源码还是有好处的;

猜你喜欢

转载自blog.csdn.net/qq_35605213/article/details/80690530