我的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. day10 内容大纲

    01 去年内容回顾 01 去年内容回顾 *args **kwargs: 万能参数,动态参数 * 魔性用法: 函数的定义时,* ** 聚合. 函数的执行时,* ** 打散. 形参顺序: 位置参数,*ar ...

  2. virtualBox 虚拟机下nginx设置不缓存静态文件不起作用解决办法

    最近开发的时候,调整js时会一直使用缓存文件,无法显示改动!nginx配置静态文件add_header Cache-Control no-cache;也不起作用,很苦恼! nginx配置代码:even ...

  3. java自动装箱的一个例子

    Object obj = 56; int i = (Integer)obj; 第一行等价于: Object obj = Integer.valueOf(56);      Integer.valueO ...

  4. 深入理解ASP.NET MVC(7)

    系列目录 Action的定位 再次回到Controller的ExecuteCore方法,回到action调用的入口: 1 if (!ActionInvoker.InvokeAction(Control ...

  5. centos7 使用cgroup进行资源限制

    centos7中进行资源限制,使用的仍然是cgroup,只是配置接口使用的systemd. 下文将介绍如何使用systemd进行资源限制. Step1 编写unit文件 命令为my-demo.serv ...

  6. Linux CentOS6升级glibc库过程

    CentOS6升级glibc库过程 hadoop无法加载native库,可能原因是 glibc库版本过低,需要升级. 第一:安装以下软件 yum -y install zlib zlib-devel ...

  7. PHP-不同Str 拼接方法性能对比

    问题 在PHP中,有多种字符串拼接的方式可供选择,共有: 1 . , .= , sprintf, vprintf, join, implode 那么,那种才是最快的,或者那种才是最适合业务使用的,需要 ...

  8. Azure REST API (4) 在Python环境下,使用Azure REST API

    <Windows Azure Platform 系列文章目录> 之前遇到的项目中,客户需要在Python环境下,监控Azure VM的CPU利用率,在这里简单记录一下. 笔者的环境是Win ...

  9. Jenkins的详细安装

    操作环境:Windows 一.环境准备 1 安装JDK 本文采用jdk-8u111-windows-x64.exe: 2 配置tomcat 本文采用tomcat8,无需安装,配置JAVA_HOME及J ...

  10. 【AMQ】之JMS概念

    1.JMS(Java Message Service)Java消息服务,是Java20几种技术其中之一 2.JMS规范定义了Java中访问消息中间件的接口,但是没有给实现,这个实现就是由第三方使用者来 ...