You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android CursorAdapter中bindView重复添加图片三次问题求助

解决CursorAdapter中ListView Item图片重复添加的问题

你遇到的这个重复添加图片的问题,根源在于ListView的Item复用机制:bindView方法会在Item被滚动回屏幕、重新复用的时候重复执行。你当前的代码每次调用bindView都会新建一个ImageView并添加到LinearLayout里,但之前复用的Item里已经保留了上一次添加的ImageView,多次复用后自然就出现了多个重复的图片。

下面给你两种解决方案,推荐用第一种性能更好的方式:

方案一:使用ViewHolder模式(推荐)

ViewHolder模式不仅能解决重复添加的问题,还能避免每次bindView都调用findViewById,提升ListView的滚动性能。修改你的适配器代码如下:

public class girlsListFragmentCursoAdapter extends CursorAdapter {
    // 定义ViewHolder,缓存每个Item的控件
    static class ViewHolder {
        TextView girlName;
        ImageView imgExercice;
        LinearLayout linearImgRow;
    }

    public girlsListFragmentCursoAdapter(Context context, Cursor c) {
        super(context, c);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View view = LayoutInflater.from(context).inflate(R.layout.girls_list_row, parent, false);
        // 初始化ViewHolder,只在创建新Item时执行一次
        ViewHolder holder = new ViewHolder();
        holder.girlName = view.findViewById(R.id.txtvwGirlName);
        holder.linearImgRow = view.findViewById(R.id.exercices_list_row);
        // 在这里创建ImageView并添加到LinearLayout,仅执行一次
        holder.imgExercice = new ImageView(context);
        holder.linearImgRow.addView(holder.imgExercice);
        // 将ViewHolder绑定到View上,方便后续复用
        view.setTag(holder);
        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // 取出缓存的ViewHolder
        ViewHolder holder = (ViewHolder) view.getTag();
        // 设置女孩名字
        holder.girlName.setText(cursor.getString(cursor.getColumnIndexOrThrow("nombre")));
        // 根据数据库字段判断是否显示图片
        if (cursor.getString(cursor.getColumnIndexOrThrow("pull_ups")).equals("1")) {
            holder.imgExercice.setImageResource(R.drawable.push_ups);
            holder.imgExercice.setVisibility(View.VISIBLE);
            Toast.makeText(context,"Pull ups: " +cursor.getString(cursor.getColumnIndexOrThrow("pull_ups")),Toast.LENGTH_SHORT ).show();
        } else {
            // 不满足条件时隐藏图片,避免复用残留
            holder.imgExercice.setVisibility(View.GONE);
        }
    }
}

方案二:清空LinearLayout后再添加(简单但性能稍差)

如果不想修改太多代码,也可以在每次bindView时先清空LinearLayout的所有子View,再根据条件添加图片:

@Override
public void bindView(View view, Context context, Cursor cursor) {
    TextView girlName;
    LinearLayout linearImgRow = (LinearLayout) view.findViewById(R.id.exercices_list_row);
    girlName = view.findViewById(R.id.txtvwGirlName);
    
    // 先清空LinearLayout中的所有子View,避免复用残留
    linearImgRow.removeAllViews();
    
    if (cursor.getString(cursor.getColumnIndexOrThrow("pull_ups")).equals("1") ) {
        ImageView imgExercice = new ImageView(context);
        imgExercice.setImageResource(R.drawable.push_ups);
        linearImgRow.addView(imgExercice);
        Toast.makeText(context,"Pull ups: " +cursor.getString(cursor.getColumnIndexOrThrow("pull_ups")),Toast.LENGTH_SHORT ).show();
    }
    girlName.setText(cursor.getString(cursor.getColumnIndexOrThrow("nombre")));
}

关键提醒

ListView的Item复用是Android列表组件的核心优化点,在编写Adapter时一定要考虑到复用场景,不然很容易出现重复内容、布局错乱、内存浪费等问题。ViewHolder模式是处理这类问题的标准方案,建议优先使用。

内容的提问来源于stack exchange,提问作者Kargol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:45:23