RecyclerView中CheckBox复用问题


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

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


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


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


1.

  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.

  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.

  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.

  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 的标志,基本这样就解决了。

  1.   
相关文章
相关标签/搜索