Reputation: 1866
I know it's a very old question but even after referring a lot of solutions nothing could solve my issue . Actually I'm trying to remove items of recyclerview on longclick
but I'm getting following error .
By the way I'm not getting any error while deleting the last item but when I'm trying to delete any other item after deleting other than last item I'm getting the following error.
Error:
java.lang.ArrayIndexOutOfBoundsException: length=12; index=-1
at java.util.ArrayList.remove(ArrayList.java:401)
at community.infinity.message.MessageAdapter$1$1$1$1.run(MessageAdapter.java:219)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
My Code:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message message = mMessages.get(position);
holder.setMessage(message.getMessage());
holder.msgContainer.setOnLongClickListener(view -> {
int position = holder.getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mMessages.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mMessages.size());
}
return false;
});
}
}
}
Upvotes: 0
Views: 1070
Reputation: 845
Personally I used to have the click listener outside of the adapter(in the fragment/activity) in
public void onBindViewHolder(ViewHolder holder, int position)
{
//I'm saving here the position of the current item
holder.rootView.setTag(position);
//you set the listener functionality from the fragment/activity by sending
//to the constructor of your adapter
holder.setLongClickListener(mListener);
//init other fields of your item
...
}
// a function that will responsible to update the list without the deleted item
public void setData(List<Data> data)
{
mData = data;
notifyDataSetChanged();
}
}
fragment/activity
your activity/fragment should implement the interface long click listener
public class MyFragment extends Fragment implements View.LongClickListener
{
...
public boolean onLongClick(View view)
{
int selectedIndex = (int)view.getTag();
mData.remove(selectedIndex);
mAdapter.setData(mData);
return true;
}
}
Don't forget to initialize the adapter with this, it needs your onClickListener implementation.
Upvotes: 0
Reputation: 54194
There's two problems here.
First, there's no need to call notifyItemRangeChanged()
after you call notifyItemRemoved()
. The call to notifyItemRemoved()
will adjust the rest of the data set correctly.
Second, holder.getAdapterPosition()
will sometimes return NO_POSITION
(defined as -1
). This will happen when the view holder knows that it was previously bound to an item that is no longer in the adapter, and hasn't been re-bound yet. Since you just called notifyItemRemoved(holder.getAdapterPosition())
, the holder's adapter position has been marked as invalid and will now be returned as -1
.
If you absolutely must call notifyItemRangeChanged()
, re-write your code as follows:
int position = holder.getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mMessages.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mMessages.size());
}
Upvotes: 3