RecyclerView和ListView的复用BUG以及解决办法

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进行状态赋值,以及阅读标记

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值