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

Android应用运行报IndexOutOfBoundsException崩溃,附GridproductAdapter源码

问题根因

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.groceryshoppingsystem, PID: 13531
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at com.example.groceryshoppingsystem.Adapters.GridproductAdapter.getView(GridproductAdapter.java:65)

该错误是horizontalProductModelList为空时,你尝试访问其下标为0的元素导致的。直接诱因是重写getCount()方法时写死返回4,完全没有和数据源长度绑定:

@Override
public int getCount() {
    return 4; // 不管数据源有没有数据,系统都会尝试渲染4个item
}

当horizontalProductModelList长度为0时,系统调用getView(0, ...),执行horizontalProductModelList.get(position)自然会抛出下标越界异常。

修复方案

1. 优先解决崩溃问题

把getCount()返回值和数据源长度绑定,同时修复逻辑错误的getItem、getItemId方法:

@Override
public int getCount() {
    // 数据源为空就返回0,不渲染任何item
    return horizontalProductModelList == null ? 0 : horizontalProductModelList.size();
}

@Override
public Object getItem(int position) {
    return horizontalProductModelList == null ? null : horizontalProductModelList.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

如果业务要求最多显示4个条目,可以改成:

@Override
public int getCount() {
    if (horizontalProductModelList == null) return 0;
    // 取数据源长度和4的最小值,最多显示4个
    return Math.min(horizontalProductModelList.size(), 4);
}

2. 修复列表复用错乱问题

现有代码只有在convertView == null时才给控件赋值,列表滑动触发复用时item会显示旧数据;且控件被声明为Adapter全局成员变量,复用时会出现内容覆盖,建议改为ViewHolder模式:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.horizontal_item, null);
        holder = new ViewHolder();
        holder.container = convertView.findViewById(R.id.MainProductID);
        holder.productImage = convertView.findViewById(R.id.item_image);
        holder.producttitle = convertView.findViewById(R.id.item_title);
        holder.productprice = convertView.findViewById(R.id.item_Price);
        holder.checkBox = convertView.findViewById(R.id.check_box);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    // 无论是否复用都重新赋值控件内容
    HorizontalProductModel currentItem = horizontalProductModelList.get(position);
    Picasso.get().load(currentItem.getProductimage()).into(holder.productImage);
    holder.producttitle.setText(currentItem.getProducttitle());
    holder.productprice.setText("EGP "+currentItem.getProductprice());

    boolean isfavourite = false;
    if (favourites != null) {
        for (int i = 0; i < favourites.size(); i++) {
            if (currentItem.getProducttitle().equals(favourites.get(i).getProducttitle())) {
                isfavourite = true;
                currentItem.setChecked(true);
                break;
            }
        }
    }
    if (isfavourite) {
        holder.checkBox.setImageResource(R.drawable.ic_baseline_favorite_24);
    } else {
        holder.checkBox.setImageResource(R.drawable.ic_baseline_favorite_shadow_24);
        currentItem.setChecked(false); // 避免复用时选中状态错乱
    }

    holder.checkBox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            DatabaseReference ref = FirebaseDatabase.getInstance().getReference("favourites")
                    .child(FirebaseAuth.getInstance().getCurrentUser().getUid());
            if (!currentItem.isChecked()) {
                currentItem.setChecked(true);
                holder.checkBox.setImageResource(R.drawable.ic_baseline_favorite_24);
                ref.child(currentItem.getProducttitle()).setValue(currentItem);
            } else {
                currentItem.setChecked(false);
                holder.checkBox.setImageResource(R.drawable.ic_baseline_favorite_shadow_24);
                ref.child(currentItem.getProducttitle()).setValue(null);
            }
        }
    });

    holder.container.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(context, ProductInfoActivity.class);
            intent.putExtra("Product Name",currentItem.getProducttitle());
            intent.putExtra("Product Price",currentItem.getProductprice());
            intent.putExtra("Product Image",currentItem.getProductimage());
            intent.putExtra("Product ExpiryDate",currentItem.getExpiredDate());
            intent.putExtra("Product IsFavorite",String.valueOf(currentItem.isChecked()));
            intent.putExtra("Is Offered","no");
            context.startActivity(intent);
        }
    });

    return convertView;
}

// 新增ViewHolder内部类
static class ViewHolder {
    ConstraintLayout container;
    ImageView productImage;
    TextView producttitle, productprice;
    ImageView checkBox;
}

3. 额外优化

构造Adapter时先做空值处理,避免后续频繁判空:

public GridproductAdapter(List<HorizontalProductModel> horizontalProductModelList, List<favouritesClass> favourites, Context context) {
    this.horizontalProductModelList = horizontalProductModelList == null ? new ArrayList<>() : horizontalProductModelList;
    this.favourites = favourites == null ? new ArrayList<>() : favourites;
    this.context = context;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:45:07