RecyclerView中使用checkbox遇到的问题

在使用RecyclerView时,遇到Checkbox的OnCheckedChangeListener在视图回收时意外触发的问题,导致选中状态被错误地改变。为解决此问题,通过在bind时设置Checkbox的tag为当前位置,并在onViewRecycled时将tag设为非法值,避免了事件逻辑的混乱,成功解决了Checkbox在RecyclerView中复用引发的困扰。


今天用recyclerview时候发现checkbox重复使用会导致OnCheckedChangeListener 出现一个不太友好的问题,问题是这样的:

Recyclerview 会回收使用组件,回收checkbox的时候会触发OnCheckedChangeListener 事件,导致我们写的listener中的逻辑会被打乱


比如我选中了一个checkbox,那么当view滚动导致这个checkbox 滑动出可视范围的时候 ,OnCheckedChangeListener事件会被触发,这样相当于自动把我选中的取消了。


为了解决这个为题巨硬了一下,发现stackoverflow上面也没找到特别合适的方法,最后自己搞了一个办法,还是比较简洁的,直接上代码:


1.

       public ViewHolder(View itemView) {
            super(itemView);
            root = itemView;
            cb = new CheckBox(root.getContext());
            cb.setTag(new Integer(-2));//这里
            ((LinearLayout)root).addView(cb);
        }

初始化控件的时候给他打一个tag,设置一个值,表示这个组件不显示的时候应该表示的状态


2.

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        CheckBox cb = ((ViewHolder) holder).getCheckBox();
//        System.out.println("set text");
        cb.setText(displayedData.getDisplayName(position));
        cb.setChecked(displayedData.isChosen(position));
        cb.setTag(new Integer(position));//把组件的状态更新为一个合法的状态值
        cb.setOnCheckedChangeListener(this.listener);
    }

bind的时候把这个tag设置一个合法的值,我这里因为listener事件处理的时候要用到position,所以我直接设置成position了


3.

    private CompoundButton.OnCheckedChangeListener listener =
            new CompoundButton.OnCheckedChangeListener(){
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    //System.out.println(isChecked);
                    //System.out.println(buttonView.getTag());
                    int index = (int)buttonView.getTag();//事件处理前要判断状态
                    if (index == -2) return;
                    if(isChecked){
                        displayedData.addToTasks(index);
                    }else{
                        displayedData.removeFromTasks(index);
                    }
                }
            };

然后是listener这里,进行逻辑处理之前判断一下状态,如果是非法状态就不执行我们的逻辑了


4.

    @Override
    public void onViewRecycled(RecyclerView.ViewHolder holder) {
        CheckBox cb = ((ViewHolder) holder).getCheckBox();
        cb.setTag(new Integer(-2));
        super.onViewRecycled(holder);
    }

这段应该是最重要的了,onViewRecycled这个方法会在这个组件脱离可视范围,进入android自己的回收缓存时候调用,那么我们这个时候要把tag改成非法值,告诉listener这个时候不要执行我们的逻辑了


另外还有一个onFailedToRecycleView方法,不过既然这个组件没被回收,那么也不会出现问题咯,所以就不用管了


主要思路就是给组件一个in user or not 的标志,基本这样就解决了。


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值