【问题标题】:Removing element from adapter throws Index out of bound exception从适配器中删除元素会引发 Index out of bound 异常
【发布时间】:2019-04-04 18:19:57
【问题描述】:

我有两个回收站视图。第一个 recyclerview 基本上是一个数据列表,我可以在其中选择一个项目及其数量,我将这个选择的项目数据存储到一个地图中。第二个是所选数据的列表。我是从地图中获取 values() 生成的。第二个也有类似的viewholder,我也可以在那里改变数量。一个数量达到零我从列表中删除该项目并尝试 notifydatasetChanged()。

问题是从第二个列表中删除项目无法正常工作,应用程序因错误而崩溃

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder

我在我的第一个 Recycler 上使用侦听器接口,以便在更改数量并将项目添加到地图时。第二个回收器的适配器会收到更改通知。下面是我用来更新第二个回收站视图的代码。

public void updateList(){
        mMap = ((UserMainActivity)getActivity()).getItemMap();

        inputs.clear();
       // adapter.notifyDataSetChanged();

        adapter = new MyCartAdapter(inputs,getContext());
        cartList.setAdapter(adapter);
        for(AllItems t:mMap.values()) {
              inputs.add(t);
        }
        adapter.notifyDataSetChanged();
    }

下面是我的第二个回收器视图的适配器。我在哪里更改所选项目的数量。

public class MyCartAdapter  extends RecyclerView.Adapter<MyCartAdapter.MyCartViewHolder>{
private List<AllItems> listItems1;
private Context context;
private Typeface typeface;



public MyCartAdapter(List<AllItems> listItems1, Context context) {
    this.listItems1 = listItems1;
    this.context = context;
}

@NonNull
@Override
public MyCartAdapter.MyCartViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.cart_items_layout, parent, false);

    return new MyCartViewHolder(v);
}

@Override
public void onBindViewHolder(@NonNull final MyCartAdapter.MyCartViewHolder holder, final int position) {

    final AllItems orderItem = listItems1.get(position);
    holder.setProductImage(orderItem.getImageUrl(),context);
    holder.name.setText(orderItem.getName());
    String price = String.valueOf(orderItem.getPrice());
    holder.price.setText(price);

    final HashMap<String, AllItems> items = ((UserMainActivity)context).getItemMap();
    holder.counter.setText(orderItem.getQuantity());

    holder.add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String quantity = String.valueOf(holder.counter.getText());
            int count = Integer.parseInt(quantity)+1;
            holder.counter.setText(String.valueOf(count)); 
            String url = orderItem.getImageUrl();
            AllItems newitem = new AllItems(orderItem.getName(),orderItem.getComname(),url, String.valueOf(count),orderItem.getWeight,orderItem.getPrice());
            ((UserMainActivity)context).addItem(orderitemname,newitem);
          //  notifyItemChanged(position);
        }
    });
//counter text iitem.textview showing the quantity of the selected item . integer count returns the value of counter text below i am checking if its zero than it simply sets the value to zero and else reduce it and update the map.
    holder.minus.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String counterText = String.valueOf(holder.counter.getText());
            int count = Integer.parseInt(counterText);
            if (count==0){
                holder.counter.setText("0");
            }
            if (count==1){
                holder.counter.setText("0");
                AllItems item = items.get(orderItem.getName());
                if (item!=null){
                    String orderit = orderItem.getName();
                    ((UserMainActivity)context).removeItem(orderit);
// here i am removing the value from the list which throws the exception 
                    listItems1.remove(position);
                      notifyItemRemoved(position);
                }
            }
            if (count>1){
                String quantity = String.valueOf(count-1);
                holder.counter.setText(quantity);
                String orderitemname = orderItem.getName();
                String url = orderItem.getImageUrl();
                String weight = "100";
                long weightl = Long.parseLong(weight);
                AllItems newitem = new AllItems(orderItem.getName(),orderItem.getComname(),url, quantity,weight,orderItem.getPrice());
                ((UserMainActivity)context).addItem(orderitemname,newitem);
             //   listItems1.set(position, newitem);
             //   notifyItemChanged(position);

            }
        }
    });

}

@Override
public int getItemCount() {
    return listItems1.size();
}



public class MyCartViewHolder extends RecyclerView.ViewHolder {
    public TextView name,price,count,comname;
    public TextView weight;
    LinearLayout add,minus;
    TextView counter;

    public MyCartViewHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.ProName);
        price = (TextView) itemView.findViewById(R.id.proPrice);
        weight = (TextView) itemView.findViewById(R.id.ProWeight);
        counter = (TextView) itemView.findViewById(R.id.counter);
        add = (LinearLayout) itemView.findViewById(R.id.addLin);
        minus= (LinearLayout) itemView.findViewById(R.id.minusLin);
    }

    public void setProductImage(final String thumb_image, final Context ctx){
        productImage = (ImageView) itemView.findViewById(R.id.ProImage);
        Picasso.with(ctx).setIndicatorsEnabled(false);
        Picasso.with(ctx)
                .load(thumb_image)
                .networkPolicy(NetworkPolicy.OFFLINE)
                .placeholder(R.drawable.basket_b).into(productImage, new Callback() {
            @Override
            public void onSuccess() {
            }
            @Override
            public void onError() {
                Picasso.with(ctx).load(thumb_image).placeholder(R.drawable.basket).into(productImage);
            }
        });
 }
    public void setComname(String name){
        comname = (TextView)itemView.findViewById(R.id.proComName);
        comname.setText(name);
    }
}
}

【问题讨论】:

  • 是否可以发布完整的代码?至少适配器,如果您也可以发布类代码会更好。
  • 我已经更新了上面的代码。

标签: android android-recyclerview


【解决方案1】:

这让我大吃一惊:

listItems1.remove(position);
notifyItemChanged(position);

notifyItemChanged() 方法的存在是为了告诉适配器给定位置的数据已经改变,并且应该重新绑定 ViewHolder。这不是你在做什么;您正在移除一个项目。

可能您的应用程序崩溃了,因为您要删除数据集中的最后一项(例如位置 10),然后告诉适配器位置 10 的项目已更改...但现在是数据集中的最大位置是 9。

相反,您应该使用notifyItemRemoved() 方法。

listItems1.remove(position);
notifyItemRemoved(position);

【讨论】:

  • 我尝试使用 notifyItemRemoved 但它显示 java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 当我删除最后一个位置时
猜你喜欢
  • 1970-01-01
  • 2021-02-06
  • 2018-12-10
  • 2017-02-03
  • 2021-05-04
  • 2017-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多