Android GridView上滑时条目重复且无法正常滚动问题求助
解决GridView向上滚动条目重复、滚动异常的问题
嘿,我仔细看了你的代码,问题主要出在ViewHolder的作用域和一些视图复用的细节上,咱们一步步来修复:
核心问题:ViewHolder的作用域错误
你把ViewHolder holder声明成了Adapter的成员变量,而不是getView()方法里的局部变量。BaseAdapter的getView()会被频繁调用(滚动时复用视图),成员变量会被所有条目共享,导致不同position的视图数据互相覆盖——这就是向上滚动时出现重复、滚动异常的根本原因。
其他需要修复的细节问题
除了上面的核心问题,还有几个小问题会影响视图复用和滚动性能:
1. 修正ViewHolder的作用域
把ViewHolder holder移到getView()方法内部作为局部变量,确保每个条目都有独立的holder引用,避免数据交叉覆盖。
2. 正确实现getItem和getItemId方法
原来的getItem()返回null、getItemId()返回0,不符合Adapter规范,可能干扰GridView的复用逻辑,改成返回对应的数据和唯一id。
3. 移除循环内的notifyDataSetChanged
在recently_beans的循环里调用notifyDataSetChanged()会导致Adapter频繁刷新,严重影响滚动流畅度,完全没必要,直接设置视图状态即可。
4. 重置Like图标的默认状态
当当前商品不在recently_beans列表中时,要把like_image重置为默认图标(比如R.drawable.dislike),否则复用视图时会保留之前条目的状态,导致显示错误。
5. 优化Picasso加载逻辑
添加占位图提升用户体验,同时减少重复调用mProducts.get(position)的次数,提升代码效率。
修复后的完整Adapter代码
private class ProductAdapter extends BaseAdapter { @Override public int getCount() { return mProducts != null ? mProducts.size() : 0; } @Override public Object getItem(int position) { // 返回对应position的商品数据,符合Adapter规范 return mProducts != null ? mProducts.get(position) : null; } @Override public long getItemId(int position) { // 返回商品id或position,这里假设prdid是可转long的字符串,也可以直接返回position return mProducts != null ? Long.parseLong(mProducts.get(position).prdid) : position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { // 把ViewHolder改成getView的局部变量! ViewHolder holder; if (convertView == null) { LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.product_layout, null); holder = new ViewHolder(); holder.product_name = (TextView) convertView.findViewById(R.id.product_name); holder.product_descr = (TextView) convertView.findViewById(R.id.product_desc); holder.product_price = (TextView) convertView.findViewById(R.id.product_price); holder.product_pic = (ImageView) convertView.findViewById(R.id.iv_division_img); holder.product_share = (ImageView) convertView.findViewById(R.id.productshare_button); holder.like_image=(ImageView) convertView.findViewById(R.id.like_image); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } if (mProducts != null) { final Product product = mProducts.get(position); // 提前获取当前商品,避免重复调用 // 处理图片加载 String url = "http://staggershop.pivalue.net/assets/product_images/" + product.product_image; String urls = url.replaceAll(" ", "%20"); Picasso.with(getApplicationContext()) .load(urls) .resize(300,300) .noFade() .placeholder(R.drawable.home_brands) // 添加占位图提升体验 .error(R.drawable.home_brands) .into(holder.product_pic); // 设置文本内容 holder.product_name.setText(product.product_name); holder.product_descr.setText(product.product_description); holder.product_price.setText(product.product_price); // 打开价格显示的注释 // 处理Like图标状态 boolean isLiked = false; if (!recently_beans.isEmpty()) { for(int i=0; i<recently_beans.size(); i++) { if (product.prdid.equals(recently_beans.get(i).prod_id)) { isLiked = true; break; // 找到匹配项就跳出循环,提升性能 } } } // 不管是否匹配都设置图标,避免复用残留状态 holder.like_image.setImageResource(isLiked ? R.drawable.like : R.drawable.dislike); } holder.product_share.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { BottomSheetFragment bottomSheetFragment = new BottomSheetFragment(); bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag()); } }); holder.like_image.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { if (mProducts == null) return; final Product product = mProducts.get(position); boolean isLiked = false; int likedIndex = -1; if (!recently_beans.isEmpty()) { for (int i = 0; i < recently_beans.size(); i++) { if (product.prdid.equals(recently_beans.get(i).prod_id)) { isLiked = true; likedIndex = i; break; } } } // 切换图标与收藏状态 if (isLiked) { holder.like_image.setImageResource(R.drawable.dislike); // 这里建议改为移除收藏的逻辑,你原来的Inserfavorite可能是笔误 // Removefavorite(product.prdid); } else { holder.like_image.setImageResource(R.drawable.like); Inserfavorite(product.prdid); recently_beans.add(new RecentlyBean(product.prdid)); // 更新本地收藏列表 } // 仅在数据修改后调用一次刷新 notifyDataSetChanged(); } }); } }); convertView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mProducts == null) return; Inserrecent(mProducts.get(position).prdid); Intent intent = new Intent(Products_activity.this, Product_description.class); intent.putExtra("PROD_ID", mProducts.get(position).prdid); // 传递商品ID给详情页 startActivity(intent); } }); return convertView; } public static class ViewHolder { public TextView product_name; public TextView product_descr; public TextView product_price; public ImageView product_pic ; public ImageView product_share; public ImageView like_image; } }
额外建议
- 你的
product.xml代码不完整,确保布局标签都正确闭合,否则可能导致视图测量异常,影响滚动效果。 - 可以考虑用
RecyclerView替代GridView,它的复用机制更完善,性能更好,也是官方当前推荐的列表组件。
内容的提问来源于stack exchange,提问作者raviteja
相关产品推荐
相关产品推荐

