RecyclerView和ListView的复用BUG
- BUG出现的场景举例
- 简单的介绍复用机制
- 复用机制BUG的解决方式
BUG出现场景举例
- 当想实现listview的多选情况时,滑动出现,checkbox错乱,也就是没有选中的被选中了
- 当listview想要实现点击变色实现阅读过标记变色时,滑动后出现未阅读的也变色了
复用机制的简单介绍
- 当listView每要展示一个item的时候就会向adapter索要一个view,也就是调用adapter的getView()方法
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item1, null);
holder = new ViewHolder();
holder.textView = (TextView)convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
上面列出baseadapter中getView的常用写法,如果我们先不看converview,那么每调用一次getview方法,getview方法就会inflater一次,如果有很多item,那这个方法就会调用很多次,inflater又是一个IO操作,是非常消耗资源的,所以google给我们提供了Recycler机制,getView(int position, View convertView, ViewGroup parent),converView就是Recycler为我们缓存之前的item,
- 第一点:Recycler中最多有几个缓存? 缓存个数=屏幕可见ite数+itemType个数
- 第二点:从第几个item开始开始复用converview? 很多人在刚接触的时候会以为是在 屏幕可见item数+1 个item时候使用converView, 但实际上是在
屏幕可见item数+3 个item是复用第1个item ,
屏幕可见item数+4 个item是复用第2个item ,
屏幕可见item数+5 个item是复用第3个item ,
屏幕可见item数+6 个item是复用第4个item , - 第三点 :因为我们在创建每一个item的时候都对item中的每一个控件赋予了不同的内容,所以我们很难了解,所以这里我们只对 屏幕可见item数+1 个item进行赋予内容(因为屏幕可见item数+3时就复用第一个item了。所以我们不给它赋予内容,因为我的模拟器屏幕可见item数是4,所以我的判断条件是position<6)
if (position<6){
boolean hasRead = CasheUtils.getBooble(activity, news.get(position).id + "", false);
viewHolder.date.setText(news.get(position).pubdate);
viewHolder.title.setText(news.get(position).title);
if (hasRead){
viewHolder.title.setTextColor(Color.GRAY);
}else {
viewHolder.title.setTextColor(Color.BLACK);
}
ImageLoader.getInstance().displayImage(Constants.BASE_URL + news.get(position).listimage, viewHolder.newsIcon);
if (position%3==0){
convertView.setBackgroundColor(Color.GREEN);
}
}
在这里大家可以看到这里完全可见item数目为4,但是第一条还是可见的,最上面的绿边是第一条item的底部,最后一条露出了一小半,也就是第六条也是可见的,这时候converView是空的,这也就是为什么不是在 屏幕可见item数+1和屏幕可见item数+2时候使用converView而是在屏幕可见item数+3的时候复用converView,因为像这样,屏幕可见item数+1 只显示一半的时候 第一个item还未进入Recycler中,也就是converView为空,不能复用。
因为我们只给前5个item进行了赋予内容,屏幕可见item数+1 赋予了内容,刚好在屏幕可见item数+2的时候复用converView, 按照之前说的,屏幕可见item数+2复用第一个item,那我们来看一个第七个item是否和第一个item内容一样
下面是1-5个item图片
接下来是5-8的item图片
这里大家可以看到第七条和第一条一模一样,第八天和第二条一模一样,正式因为这样,所以才会出现 在实现多选时,如果滑动了,没有选中的item也会被选中,因为getview()的时候没有对checkbox进行状态设置,也就是第七个item的checkbox直接复用了第一个item的checkbox的状态,这个道理同样适用于阅读标记功能,一样的也适用于recyclerview控件上
解决办法
就是同item中间中其他控件(textView等等)一样,在get每一个itemView的时候对checkBox进行状态赋值,以及阅读标记