【Android】RecyclerView复用CheckBox的异常状态

三三要成为安卓糕手

一:问题场景引入

问题描述:勾选了2、4两个item的check框,向下滑动,新的item上来莫名其妙也被勾选上了!

分析向上滑动,Holder被划出,Holder会被复用,就造成了下面的item被打了勾的Holder利用,就造成了上述场景发生的bug问题

需求:一句话就是跟RecyclerView中ViewHolder的复用有关系

打勾的check勾选框所在的Holder被回收复用后被新的item利用,根本原因就是check是跟Holder捆绑在一起的,

打个比方一个被做了标记的杯子,装过咖啡,又装奶茶;可以说咖啡和奶茶都被一个做过标记的杯子装过

二:解决方案

核心:控制勾选状态,在绑定Holder中Check框的状态取决于Article中的check属性;check属性由监听器控制,就是这样;

非常言简意赅

三:需要修改增添的代码

1:新增check属性

Article类中新增check属性,并添加get和set方法

java 复制代码
import android.widget.CheckBox;

public class Article {
    private boolean check;

    public boolean isCheck() {
        return check;
    }

    public void setCheck(boolean check) {
        this.check = check;
    }
}

2:xml布局加Check框

给MyViewHolder类对应的xml布局加上一个Check框

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="12dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <CheckBox
            android:id="@+id/check_box"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="勾选"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_author" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

3:勾选监听器控制check属性

java 复制代码
    /**
     *  有一条item就调用一次这个方法
     */
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Log.i(TAG, "onBindViewHolder: position" + position);

        Article article = articles.get(position);
        holder.ivPicture.setImageResource(article.getPicture());
        holder.tvTitle.setText(article.getTitle());
        holder.tvAuthor.setText(article.getAuthor());
        holder.checkBox.setChecked(article.isCheck());
    }
java 复制代码
public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            ivPicture = itemView.findViewById(R.id.iv_picture);
            tvTitle = itemView.findViewById(R.id.tv_title);
            tvAuthor = itemView.findViewById(R.id.tv_author);
            checkBox = itemView.findViewById(R.id.check_box);

            checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    Article article = articles.get(getLayoutPosition());
                    article.setCheck(isChecked);
                }
            });
        }
相关推荐
用户059540174468 分钟前
Redis缓存回滚踩坑实录:一个配置失误,让我在凌晨3点丢了3000条数据
前端·css
都叫我大帅哥37 分钟前
给 Java 程序员的 CSRF 攻击详解:从原理到防御实战
java
江南十四行1 小时前
Spring框架核心(上)——IoC控制反转与DI依赖注入详解
java·后端·spring
kyriewen1 小时前
别再这样写条件渲染了——你的React组件里藏着这5种定时炸弹
前端·javascript·react.js
IT_陈寒1 小时前
Redis缓存击穿把我坑惨了,原来这样设过期时间才靠谱
前端·人工智能·后端
用户938515635072 小时前
从"坐电梯"到"前端路由"——深入理解 Hash 路由原理
前端·typescript·全栈
fb_123452 小时前
Linux磁盘分区从入门到实操:MBR_GPT全解析+分区工具实战指南
java·linux·gpt
梦想CAD控件2 小时前
网页端CAD的图形选择、编辑与夹点操作教程
前端·javascript·node.js
妙码生花2 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十二):管理员权限检查中间件,AI 随意放行预闯大祸
前端·后端·go
创安电气研究所2 小时前
用 Node.js 将变频器运行数据接入 MQTT
后端