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
相关产品推荐
相关产品推荐

