Recycleview checkbox 复用出现混乱解决方法

今天在做项目的一个我的收藏页面时要实现这么一个效果:
这里写图片描述
每个item 前面都有一个checkbox ,主要布局是recycleview 。当我们选中某项时,继续往下滑动下面某个的checkbox也会变成选中状态。
解决方法一比较暴力 viewHolder.setIsRecyclable(false);
这样viewholder就不进行复用,也不存在checkbox 混乱选中的问题了,但是 你滑动的时候卡的要死。

第二种就是在获取到的bean中设置一个标志位,但是需要修改bean 。虽然只是加个字段的问题,但是不建议。

第三种就是用个辅助list记录选中的item. 这还不够,还要配合viewholder的settag().

1.在绑定view的时候
viewHolder.checkBox.setTag(new Integer(position));//设置tag 否则划回来时选中消失

    if (checkPositionlist != null) {
        ((MyViewHolder) holder).checkBox.setChecked((checkPositionlist.contains(new Integer(position)) ? true : false));
    } else {
        ((MyViewHolder) holder).checkBox.setChecked(false);
    }

2.选中监听事件:

 viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                MyCollectionBaseBean baseBean = data.getFavoritesList().get(position);

                if (isChecked) {
                    //Log.e("fangchao 1", viewHolder.checkBox.getTag() + "");
                    if (!checkPositionlist.contains(viewHolder.checkBox.getTag())) {//这句要有 ,否则不复用了,但是你再滑动回去的时候,都成了为选中。这是因为你的item滑出可视范围时,就会触发oncheckchange事件,所以用第一步绑定的tag进行二次判断。防止选中的丢失
                        checkeddata.add(baseBean);
                        checkPositionlist.add(new Integer(position));
                    }
                } else {
                    //Log.e("fangchao 2", viewHolder.checkBox.getTag() + "");
                    if (checkPositionlist.contains(viewHolder.checkBox.getTag()))//这句同上,二次判断{
                        checkeddata.remove(baseBean);
                        checkPositionlist.remove(new Integer(position));
                    }
                }
            }
        });

完整代码,自己摘着看:


/**
 * Created By Fangchao On 2015/3/5
 */
public class CollectionAdapter extends FooterAdapter {
    private MyCollectionListBean data;// 元数据
    private List<MyCollectionBaseBean> checkeddata = new ArrayList<>();// 选中的数据
    private ImageLoader mImageLoader;
    private List<Integer> checkPositionlist;

    public CollectionAdapter(MyCollectionListBean data) {
        this.data = data;
        mImageLoader = new ImageLoader(MyApplication.getInstance()
                .getRequestQueue(), BitmapCache.getInstance());
        checkPositionlist = new ArrayList<>();
    }


    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView txt_onsale, txt_mj, txt_present, goodsname, goods_describe;
        public TextView price, mark_price, commentsnums;
        CheckBox checkBox;
        NetworkImageView goods_img;
        public View v;

        public MyViewHolder(View v) {
            super(v);
            this.v = v;
            txt_onsale = (TextView) v.findViewById(R.id.txt_onsale);
            txt_mj = (TextView) v.findViewById(R.id.txt_mj);
            txt_present = (TextView) v.findViewById(R.id.txt_present);
            goods_describe = (TextView) v.findViewById(R.id.tv_production_describ);
            goodsname = (TextView) v.findViewById(R.id.tv_goods_name);
            price = (TextView) v.findViewById(R.id.tv_goods_price);
            mark_price = (TextView) v.findViewById(R.id.tv_goods_markprice);
            commentsnums = (TextView) v.findViewById(R.id.tv_goods_commentsnums);
            checkBox = (CheckBox) v.findViewById(R.id.collection_cb);
            goods_img = (NetworkImageView) v.findViewById(R.id.mycollection_item_image);

        }


    }

    @Override
    public boolean useFooter() {
        return true;
    }

    @Override
    public RecyclerView.ViewHolder onCreateContentItemViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_collection, parent, false);

        MyViewHolder vh = new MyViewHolder(v);
        return vh;
    }

    @Override
    public void onBindContentItemView(RecyclerView.ViewHolder holder, final int position) {
        MyViewHolder viewHolder = (MyViewHolder) holder;
        // viewHolder.setIsRecyclable(false);
        viewHolder.goodsname.setText(data.getFavoritesList().get(position).getGoods().getGoodsName());
        if (StringUtils.isBlank(data.getFavoritesList().get(position).getGoods().getGoodsSlogan())) {
            viewHolder.goods_describe.setVisibility(View.GONE);
        } else {
            viewHolder.goods_describe.setVisibility(View.VISIBLE);
            viewHolder.goods_describe.setText(data.getFavoritesList().get(position).getGoods().getGoodsSlogan());
        }
        viewHolder.price.setText(PriceTools.formatStr(data.getFavoritesList().get(position).getGoods().getShopPrice()));
        viewHolder.price.setTextColor(Color.parseColor("#E5004B"));
        viewHolder.mark_price.setText(PriceTools.formatStr(data.getFavoritesList().get(position).getGoods().getMarketPrice()));
        viewHolder.mark_price.setBackgroundResource(0);
        viewHolder.mark_price.getPaint().setFlags(
                Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); // 设置中划线并加清晰
        viewHolder.commentsnums.setText(data.getFavoritesList().get(position).getGoods().getCommentCount());
        viewHolder.checkBox.setTag(new Integer(position));//设置tag 否则划回来时选中消失
        //checkbox  复用问题
        if (checkPositionlist != null) {
            ((MyViewHolder) holder).checkBox.setChecked((checkPositionlist.contains(new Integer(position)) ? true : false));
        } else {
            ((MyViewHolder) holder).checkBox.setChecked(false);
        }
        //Log.e("ffff",position+"");
        viewHolder.goods_img.setDefaultImageResId(R.drawable.item_default_img);
        viewHolder.goods_img.setErrorImageResId(R.drawable.item_default_img_err);
        viewHolder.goods_img.setImageUrl(data.getFavoritesList().get(position).getGoods().getImgFile(), mImageLoader);
        if (data.getFavoritesList().get(position).getGoods().getIsOnSale().equals("false")) {
            //下架
            viewHolder.price.setText("本商品已经下架");
            viewHolder.price.setTextColor(Color.GRAY);
            viewHolder.mark_price.setText("");
        } else if (data.getFavoritesList().get(position).getGoods().isIsNoStock()) {
            //缺货
            viewHolder.mark_price.setBackgroundResource(R.drawable.ticket_is_outof_date_bg);
            viewHolder.mark_price.setText(" 缺货 ");
            viewHolder.price.setTextColor(Color.GRAY);
            viewHolder.mark_price.getPaint().setFlags(0);
        }
        //cb 的选中事件
        onchecked(viewHolder, position);


    }

    private void onchecked(final MyViewHolder viewHolder, final int position) {

        viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                MyCollectionBaseBean baseBean = data.getFavoritesList().get(position);

                if (isChecked) {
                    //Log.e("fcccc 1", viewHolder.checkBox.getTag() + "");
                    if (!checkPositionlist.contains(viewHolder.checkBox.getTag())) {
                        checkeddata.add(baseBean);
                        checkPositionlist.add(new Integer(position));
                    }
                } else {
                    //Log.e("fcccc 2", viewHolder.checkBox.getTag() + "");
                    if (checkPositionlist.contains(viewHolder.checkBox.getTag())) {
                        checkeddata.remove(baseBean);
                        checkPositionlist.remove(new Integer(position));
                    }
                }
            }
        });
    }

    @Override
    public int getContentItemCount() {
        if (data != null)
            return data.getFavoritesList().size();
        else return 0;
    }

    @Override
    public int getContentItemType(int position) {
        return 0;
    }

    public void getdata(MycheckListener listener) {
        listener.getcheckeddata(checkeddata);
    }

    public interface MycheckListener {
        void getcheckeddata(List<MyCollectionBaseBean> listBean);
    }
}
RecyclerView复用机制是为了优化性能而设计的,它会复用已经创建的 View,来减少创建新 View 的次数,从而提高滑动的流畅度。在 RecyclerView 中,每当一个 item 滑出屏幕时,其对应的 View 会被回收,并放入到一个 ViewPool 中,以供后续使用。在需要新的 item 时,先从 ViewPool 中获取一个可用的 View,然后通过 onBindViewHolder() 方法将数据绑定到这个 View 上。 但是,这个复用机制也会带来一些问题,比如当 item 的布局和内容变化很大时,可能会出现数据重叠、错乱的问题。这是因为 RecyclerView复用 View 的过程中,没有清空之前 View 的状态,导致新的数据与之前的数据混合在一起。 为了解决这个问题,可以采用以下两种方法: 1. 在 onBindViewHolder() 方法中,清空之前 View 的状态。这样可以确保每次绑定新数据时,View 的状态都是干净的。比如,可以将需要清空的状态设置为默认值,或者使用 View.setTag() 方法保存状态,在下次使用时再根据 Tag 进行清空。 2. 使用不同的 ViewType。如果 item 的布局和内容变化很大,可以根据数据的类型,设置不同的 ViewType。这样就可以确保每个 View 只会被用于一种类型的数据,避免数据重叠、错乱的问题。在 onCreateViewHolder() 方法中,可以根据 ViewType 创建不同的 View。 总之,复用机制是 RecyclerView 的重要特性,可以优化滑动的性能。但是在使用时,需要注意清空之前 View 的状态,或者使用不同的 ViewType 来避免数据重叠、错乱的问题。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值