RecyclerView中CheckBox复用问题

来源:互联网 发布:mac 你的安全设置 编辑:程序博客网 时间:2024/05/16 10:10


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

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


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


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


1.

[java] view plain copy
print?
  1. public ViewHolder(View itemView) {  
  2.      super(itemView);  
  3.      root = itemView;  
  4.      cb = new CheckBox(root.getContext());  
  5.      cb.setTag(new Integer(-2));//这里  
  6.      ((LinearLayout)root).addView(cb);  
  7.  }  
       public ViewHolder(View itemView) {            super(itemView);            root = itemView;            cb = new CheckBox(root.getContext());            cb.setTag(new Integer(-2));//这里            ((LinearLayout)root).addView(cb);        }

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


2.

[java] view plain copy
print?
  1. @Override  
  2. public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {  
  3.     CheckBox cb = ((ViewHolder) holder).getCheckBox();  
  4.       System.out.println(”set text”);  
  5.     cb.setText(displayedData.getDisplayName(position));  
  6.     cb.setChecked(displayedData.isChosen(position));  
  7.     cb.setTag(new Integer(position));//把组件的状态更新为一个合法的状态值  
  8.     cb.setOnCheckedChangeListener(this.listener);  
  9. }  
    @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.

[java] view plain copy
print?
  1. private CompoundButton.OnCheckedChangeListener listener =  
  2.         new CompoundButton.OnCheckedChangeListener(){  
  3.             @Override  
  4.             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
  5.                 //System.out.println(isChecked);  
  6.                 //System.out.println(buttonView.getTag());  
  7.                 int index = (int)buttonView.getTag();//事件处理前要判断状态  
  8.                 if (index == -2return;  
  9.                 if(isChecked){  
  10.                     displayedData.addToTasks(index);  
  11.                 }else{  
  12.                     displayedData.removeFromTasks(index);  
  13.                 }  
  14.             }  
  15.         };  
    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.

[java] view plain copy
print?
  1. @Override  
  2. public void onViewRecycled(RecyclerView.ViewHolder holder) {  
  3.     CheckBox cb = ((ViewHolder) holder).getCheckBox();  
  4.     cb.setTag(new Integer(-2));  
  5.     super.onViewRecycled(holder);  
  6. }  
    @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 的标志,基本这样就解决了。

[java] view plain copy
print?
  1.   

2 0
原创粉丝点击