从适配器中删除元素会引发索引超出范围的异常

时间:2019-04-02 15:49:17

标签: android android-recyclerview recycler-adapter

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

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

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

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

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);
    }
}
}

1 个答案:

答案 0 :(得分:1)

这对我跳了起来

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

存在notifyItemChanged()方法来告诉适配器给定位置的数据已更改,并且ViewHolder应该重新绑定。这不是您所做的不是;您正在删除一个项目。

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

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

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