我的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是一样的,知道今天改变数据后会下标越界异常;多去看一下源码还是有好处的;

ViewPager的addOnPageChangeListener和setOnPageChangeListener的区别,ViewPager改变数据后IndexOutOfBoundsException的更多相关文章

  1. [web] Get和Post区别,EncType提交数据的格式详解

    转载自:http://www.cnblogs.com/sunxucool/archive/2012/12/11/2813113.html 1. get是从服务器上获取数据,post是向服务器传送数据. ...

  2. Get和Post区别,EncType提交数据的格式详解——转自他人博客的

    1. get是从服务器上获取数据,post是向服务器传送数据. 2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到.post是通过 ...

  3. Kafka session.timeout.ms heartbeat.interval.ms参数的区别以及对数据存储的一些思考

    Kafka session.timeout.ms heartbeat.interval.ms参数的区别以及对数据存储的一些思考 在计算机世界中经常需要与数据打交道,这也是我们戏称CURD工程师的原因之 ...

  4. viewpager处理(三):让viewpager不预加载下一页

    有时候viewpager加载页面的时候,我们发现页面的数据量很大,预加载的话会消耗性能,为了节省用户流量和手机性能,所以我们想让viewpager不自动预加载下一页,怎么实现呢? viewpager预 ...

  5. 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题

    ViewPager是android-support-v4.jar包中的一个系统控件,继承自ViewGroup,专门用以实现左右滑动切换View的效果,使用时需要首先在Project->prope ...

  6. ViewPager部分源码分析一:加载数据

    onMeasure()调用populate(),完成首次数据初始化. populate()维护ViewPager的page,包括mItems和mAdapter. populate(): if (cur ...

  7. viewpager处理(一):让viewpager不能滑动

    1.实现原理: 自定义viewpager,重写onTouchEvent方法,什么触摸事件都不响应即可让viewpager不能滑动. 2.代码如下 public class NoScrollViewPa ...

  8. python2与python3的区别 ,小数据池 bytes 类型

    一.python2和3的区别 在python3中 在python2中 print('ab')方式打印内容()括号是必须要有的.   print 'ab' 可以加可以不加. 只有range   有ran ...

  9. Linux与Windows的区别(后面了解后继续更新)

    1.转自知乎上的@Haoyuan Xing得答案: Linux是一个以开发者为中心的操作系统,Windows是以消费者为中心的操作系统.这是最根本的区别,也是Linux相对于Windows的优势/劣势 ...

随机推荐

  1. 两个简单的API限流实现方案

    1, Ngnix限流 Nginx在架构中起到请求转发与负载均衡器的作用.外部req首先到Nginx监听的80端口,然后Nginx将req交给到监听8080端口的APP服务器处理.处理结果再经由Ngin ...

  2. react-redux 知识点

    React-Redux 使用 如果只使用redux,那么流程是这样的: component --> dispatch(action) --> reducer --> subscrib ...

  3. 使用 RSA 非对称加密保证数据不被篡改 java 例子代码

    原理: 对原始数据 生成有序的json 字符串,然后取 摘要,然后 对摘要 进项 分对称加密.( 不对原数据加密是应为 原数据太大,加解密速度太慢,非对称加密都不 挺慢的.在摘要函数具有雪崩效应 ,原 ...

  4. 解决Ecipse和搜狗输入法快捷键冲突问题

    非常简单,关闭掉搜狗输入的所有快捷键!

  5. py-day1-1 python的基本运算符和语句

    整体注释:  选中目标  ctrl + ?    基础: 运算符: **  表示幂函数 in  和 not in  : 比较运算符: 基本语法: pass 代表空代码,无意义,仅仅用于表示代码块: 引 ...

  6. Eureka的高可用

    问题: 现在Eureka和Client是1对1,但是Eureka挂了,就不能用了. 如何解决呢,创建多个Erurka.并且Eureka进行相互注册.如下图 怎么相互注册呢 1. 创建两个Eureka ...

  7. VS未能正确加载包

    这个方法同样适用于多个版本的VS 首先关闭VS进这里:C:\Users\用户名\AppData\Roaming\Microsoft\VisualStudio\11.0(2012是11.0,根据你的VS ...

  8. 阅读<<HDMI 1.4/2.0 Transmitter Subsystem V2.0>>笔记

    阅读<<HDMI 1.4/2.0 Transmitter Subsystem V2.0>>笔记 1.Subsystem Block Diagram 2.HDMI TX Subs ...

  9. Pandas的使用(3)---Pandas的数据结构

    Pandas的使用(3) Pandas的数据结构 1.Series 2.DataFrame

  10. 基于selector的socket并发

    server: #!_*_coding:utf-8_*_ #__author__:"Alex huang" import selectors #selector模块集成了selec ...