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

Glide加载URL列表移除RecyclerView失效链接项快速滑动抛IndexOutOfBoundsException如何解决

崩溃根因

快速滑动RecyclerView时,滑出屏幕的item对应的ViewHolder会被系统回收复用,此时Glide的异步加载失败回调才触发,调用holder.getBindingAdapterPosition()会返回RecyclerView.NO_POSITION(固定值为-1),直接用该无效下标操作ArrayList就会抛出数组越界异常。

修复方案

按以下步骤修改代码即可解决:

  • 先校验位置有效性再执行删除操作:拿到Adapter位置后,先判断是否不等于RecyclerView.NO_POSITION,且小于数据源长度,再执行删除逻辑。
  • 优化列表通知方法:删除单条item时使用notifyItemRemoved()替代notifyItemRangeChanged(),性能更高还自带删除动画。
  • 修复点击事件的下标取值问题:原有点击事件使用onBindViewHolder的入参position,该值是绑定时刻的静态值,列表item顺序/数量变化后会取值错误,改为实时调用holder.getBindingAdapterPosition()取值。
  • 回收ViewHolder时取消Glide请求:重写Adapter的onViewRecycled方法,主动取消滑出屏幕item的Glide加载请求,避免无用回调触发。

修改后完整代码

@Override
public void onBindViewHolder(@NonNull SearchViewHolder holder, int position) {
    Glide.with(context)
            .load(arrayList.get(position))
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .error(R.drawable.transparent_icon)
            .override(Constants.THUMBNAIL_SIZE, Constants.THUMBNAIL_SIZE)
            .fitCenter()
            .listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                    int adapterPos = holder.getBindingAdapterPosition();
                    // 先校验位置有效性
                    if (adapterPos != RecyclerView.NO_POSITION && adapterPos < arrayList.size()) {
                        arrayList.remove(adapterPos);
                        notifyItemRemoved(adapterPos);
                    }
                    return false;
                }

                @Override
                public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                    return false;
                }
            }).into(holder.image);

    holder.image.setOnClickListener(v -> {
        int clickPos = holder.getBindingAdapterPosition();
        if (clickPos != RecyclerView.NO_POSITION && clickPos < arrayList.size()) {
            itemStringClickListener.onItemClicked(arrayList.get(clickPos));
        }
    });
}

// 新增ViewHolder回收时取消Glide请求的逻辑
@Override
public void onViewRecycled(@NonNull SearchViewHolder holder) {
    super.onViewRecycled(holder);
    Glide.with(context).clear(holder.image);
}

注:原代码中定义的isBrokenUrl变量没有实际使用,且作为全局变量存在并发取值问题,可直接删除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 10:36:02