0

I have a RecyclerView with Adapter and ViewHolder classes, so it's 3 classes, I've added a onLongClick in my ViewHolder, when it's long clicked, the selected item will be removed, i'm removing it as the following :

            MyRV.Items.remove(getLayoutPosition());
            MyRV.mAdapter.notifyItemRemoved(getLayoutPosition());

Items :

  1. Item_1
  2. Item_2
  3. Item_3
  4. Item_4
  5. Item_5

    Removing Item 2 - Item 2 removed .
    Removing Item 3 (which is item 2 now) - Item 1 removed (item - 1) .
    

My Data items are about 7 items, So here's what's happening. When first remove, it removes the correct item, when you click on remove again, it removed the above item rather than removing the selected item, and when the size is 1, it FC because invalid size .

My question is similar to this : using notifyItemRemoved or notifyDataSetChanged with RecyclerView in Android

But the answers didn't work, none of them, from itemRange to index + 1 .

public class MyAdapterextends RecyclerView.Adapter<MyViewHolder> {

private List<MyItem> itemList;
public Context context;

public MyAdapter(Context context, List<MyItem> itemList) {
    this.itemList = itemList;
    this.context = context;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.myitem, null);
    return new MyViewHolder(layoutView);
}



@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {

    holder.From.setText(itemList.get(holder.getAdapterPosition()).getFrom());
    holder.To.setText(itemList.get(holder.getAdapterPosition()).getTo());


}

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

Activity

    LinearLayoutManager LinLayout = new LinearLayoutManager(MyActivity.this, LinearLayoutManager.VERTICAL, false);
    mAdapter = new MyAdapter(MyActivity.this, Items);

    RcView.setItemAnimator(new ItemAnimator());
    RcView.setHasFixedSize(true);
    RcView.setLayoutManager(LinLayout);
    RcView.setAdapter(mAdapter);
Community
  • 1
  • 1
Jaeger
  • 1,646
  • 8
  • 27
  • 59

2 Answers2

4

Try that:

  adapter.remove(item);
  adapter.notifyItemRemoved(position);
  adapter.notifyItemRangeChanged(position, list.count());
Alessandro Verona
  • 1,157
  • 9
  • 23
2

Ok, let's explain some basic stuff.

  • First of all, notifyDataSetChanged() refreshes the full RV layout from the Adapter list, killing all the animations. We don't want this. RV was created to save battery too, if we call all the times this method we don't do a good job.

  • To remove an item, you remove it from the list (ArrayList) and just after call notifyItemRemoved(the index of the item you just removed). Animation is performed. No need to call notifyItemChanged()! Doing that it will trigger a new binding for the item in that position.

  • Don't use getLayoutPosition() it will represent the position in the layout not the position of the list in the Adapter. To know the real position you have to call getAdapterPosition().

  • Don't call holder.getAdapterPosition() in the binding, you already have the position!

Now, you don't need to reinvent a new Adapter for every project, so, consider to adopt this Library FlexibleAdapter, since it will handle all the basic functionalities out of the box (you don't need to extend it); you customize the items for every view types you need; ViewHolder are predefined: common events are already implemented (single and long click); it maintains the state after rotation and much much more...

Davideas
  • 3,226
  • 2
  • 33
  • 51
  • Just a heads up, getPosition is now deprecated. getAdapterPosition would be suitable. – BradleyIW Oct 10 '16 at 22:39
  • I was doing the same as you commented, but i'm having the following error : `java.lang.ArrayIndexOutOfBoundsException: length=12; index=-1`, for `holder.getAdapterPosition()`, the `position` param is `final`, and a note come up to use `holder.getAdapterPosition()` instead of `position`. – Jaeger Oct 13 '16 at 00:08