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是一样的,知道今天改变数据后会下标越界异常;多去看一下源码还是有好处的;
ViewPager的addOnPageChangeListener和setOnPageChangeListener的区别,ViewPager改变数据后IndexOutOfBoundsException的更多相关文章
- [web] Get和Post区别,EncType提交数据的格式详解
转载自:http://www.cnblogs.com/sunxucool/archive/2012/12/11/2813113.html 1. get是从服务器上获取数据,post是向服务器传送数据. ...
- Get和Post区别,EncType提交数据的格式详解——转自他人博客的
1. get是从服务器上获取数据,post是向服务器传送数据. 2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到.post是通过 ...
- Kafka session.timeout.ms heartbeat.interval.ms参数的区别以及对数据存储的一些思考
Kafka session.timeout.ms heartbeat.interval.ms参数的区别以及对数据存储的一些思考 在计算机世界中经常需要与数据打交道,这也是我们戏称CURD工程师的原因之 ...
- viewpager处理(三):让viewpager不预加载下一页
有时候viewpager加载页面的时候,我们发现页面的数据量很大,预加载的话会消耗性能,为了节省用户流量和手机性能,所以我们想让viewpager不自动预加载下一页,怎么实现呢? viewpager预 ...
- 有关ViewPager的使用及解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题
ViewPager是android-support-v4.jar包中的一个系统控件,继承自ViewGroup,专门用以实现左右滑动切换View的效果,使用时需要首先在Project->prope ...
- ViewPager部分源码分析一:加载数据
onMeasure()调用populate(),完成首次数据初始化. populate()维护ViewPager的page,包括mItems和mAdapter. populate(): if (cur ...
- viewpager处理(一):让viewpager不能滑动
1.实现原理: 自定义viewpager,重写onTouchEvent方法,什么触摸事件都不响应即可让viewpager不能滑动. 2.代码如下 public class NoScrollViewPa ...
- python2与python3的区别 ,小数据池 bytes 类型
一.python2和3的区别 在python3中 在python2中 print('ab')方式打印内容()括号是必须要有的. print 'ab' 可以加可以不加. 只有range 有ran ...
- Linux与Windows的区别(后面了解后继续更新)
1.转自知乎上的@Haoyuan Xing得答案: Linux是一个以开发者为中心的操作系统,Windows是以消费者为中心的操作系统.这是最根本的区别,也是Linux相对于Windows的优势/劣势 ...
随机推荐
- 论 数据库 B Tree 索引 在 固态硬盘 上 的 离散存储
传统的做法 , 数据库 的 B Tree 索引 在 磁盘上是 顺序存储 的 , 这是考虑到 磁盘 机械读写 的 特性 . 实际上 , B Tree 是一个 树形结构 , 可以采用 链式 存储 , 就是 ...
- Anaconda 安装 Python 库(MySQLdb)的方法-(转)
安装python库的过程中,最重要的地方就是版本需要兼容.其中操作系统为64位,Python为2.X 64位,下载安装文件的时候也要注意版本匹配.其中文件名中包含的cp27表示CPython 2.7版 ...
- php调用c#的dll(转)
这几天,一直在做DES ecb模式的加解密,刚用.net实现了加解密,完了由于需要又要转型成PHP代码,费了九牛二虎之力单独用PHP没能实现,结构看到一篇php直接调用c#里生成的.dll文件的方法, ...
- .ajax向后台传递数组(转)
js部分代码 //创建一个测试数组 var boxIds = new Array(); boxIds.push(12182); boxIds.push(12183); boxIds.push(1218 ...
- js写法【2】
1.stringobject.replace(/regex/,function(capture,index,stringob){});可 用来对每个捕获执行一段脚本,返回捕获替换值. 2.arrayo ...
- Java事件监听器的四种实现方式
自身类作为事件监听器 外部类作为事件监听器 匿名内部类作为事件监听器 内部类作为事件监听器 自身类作为事件监听器: import javax.swing.*; import java.awt.*; i ...
- "上市时间: 2014年秋冬季" unicode十进制编码转中文
"上市时间: 2014年秋冬季" unicode十进制编码转中文 System.Web.HttpUtility.HtmlDecode(tmp);
- ALGO-151_蓝桥杯_算法训练_6-2递归求二进制表示位数
记: 进制转换 AC代码: #include <stdio.h> #define K 2 int main(void) { ; scanf("%d",&n); ...
- 【支付专区】之解析微信支付返回xml
public static Map<String,Object> parseBodyXml2Map(String xml){ Map<String,Object> map = ...
- C++中函数的形参为数组时,实质形参是指针
C++中函数的形参如果为数组的话,那么进行实参传递时,实参实际上换转化成指针.参考下面的例子: #include<iostream> using namespace std; void f ...