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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:18:58