I'm having a very strange error . Basically I'm trying to delete recyclerview items on LongClick but in some cases I'm getting adapter position as -1.
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();
mMessages.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mMessages.size());
return false;
});
}
}
}
From the docs: RecyclerView does not handle any adapter updates until the next layout traversal. This may create temporary inconsistencies between what user sees on the screen and what adapter contents have.
This is a common issue, just wrap your call in an if statement checking if the position isn't -1.
if (getAdapterPosition() != - 1)
getAdapterPosition() return -1.It means Adapter gets a NO_POSITION,and it always happened when you call method like notifyDataSetChanged(). we always use position like this
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
Message message = mMessages.get(position);
holder.setMessage(message.getMessage());
holder.msgContainer.setOnLongClickListener(view -> {
//you can use the position parameter directly,just set it as final
mMessages.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mMessages.size());
return false;
});
}
Related
I have a recyclerview with multiple view types and pagination enabled. Scrolling up after two pages the items are not holding the view and are duplicating. I have implemented getItemId return unique id and getViewtype return unique value. Also have the the adapter's setHasStableIds to true. Looking forward for any help.
Thank you.
getItemId
if (postList.get(position).getId()== null){
return position;
} else{
return postList.get(position).getId();
}
getItemViewType
if (postList.get(position).getPostType().equals("contest")){
return TYPE_CONTEST;
} else if(postList.get(position).getPostType().equals("suggestion")){
return TYPE_SUGGESTION;
} else{
return TYPE_POST_POLL;
}
} else{
return TYPE_HEADER;
}
Try something like this:
#Override
public int getItemViewType(int position) {
if (isValidPosition(position)) {
Dataset d = mDataset[position];
if ("contest".equals(d.getViewType())) {
return VIEW_TYPE_CONTEST;
} else if ("suggestion".equals(d.getViewType())) {
return VIEW_TYPE_SUGGESTION;
}
// all other cases here
}
// default type
return VIEW_TYPE_CONTEST;
}
and then :
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Dataset d = mDataset[position];
if (holder instanceof ContestVH) {
ContestDataset contest = (ContestDataset) d;
ContestVH vh = (ContestVH) holder;
// bind your contest views here
} else if (holder instanceof SuggestionVH) {
SuggestionDataset suggestion = (SuggestionDataset) d;
SuggestionVH vh = (SuggestionVH) holder;
// bind your suggestion views here
}
// all other cases here
}
this way your String view type is your only source of truth.
For pagination in recyclerview you should use onScrollListener this
recyclerList.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
boolean isLast = isLastItemDisplaying(recyclerView); //get last displayed item
if (loading && isLast) { //this check if your data is loading and if its last list item list will not load again
loading = false;
//get your data according to page count it will refresh your recycler list
}
}
});
because in pagination you can get data from Api on page scroll in recycler view. So data will come in chunks according to page count. For this behaviour you can use on scroll listener in recycler list and refresh data on scroll of list until last item of list arrived.
i hope it will help you :)
I have a RecyclerView with a large list of items. This RecyclerView has OnScrollListener for endless scrolling.
When an item is selected I highlight it with a specific colour and
when unselected the colour changes to normal/white.
The issue that I am facing is after selecting a few visible items in my view when I scroll up or down to select a few more items the colour of already selected items changes to white.
I tried adding a boolean variable (isSelected) in the model class and highlight the selected item but still I am facing the same issue as earlier. Currently the recyclerView allows to select just one item from the view and after some research I figured some of the concepts were taken from this article to implement single item selection. I wonder how do I modify/tweak this code to be able to select multiple items.
I am not presenting the code as it is quite huge and is confidential but if there is any general fix for this scenario then what would it be?
Background: the application is a chat app and I am showing the sent and received texts. The user should be able to select a few specific texts and should be able to share it with someone else.
Edit: I am putting the code in my onBindViewHolder:
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final PostDataColumns mPostDataColumns = data.get(position);
holder.textCardView.setBackgroundColor(mPostDataColumns.isSelected() ? getResources().getColor(R.color.long_press):
getResources().getColor(android.R.color.white));
holder.textCardView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mPostDataColumns.setSelected(!mPostDataColumns.isSelected());
if(mPostDataColumns.isSelected()) {
holder.textCardView.setBackgroundResource(R.color.long_press);
multipleSelectedPositions.add(holder.getLayoutPosition());
} else if(!mPostDataColumns.isSelected()) {
holder.textCardView.setBackgroundResource(android.R.color.white);
multipleSelectedPositions.remove(holder.getAdapterPosition());
}
//Adapter.this.onLongClick(holder, position);
return true;
}
});
holder.textCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textCardView.setBackgroundResource(android.R.color.white);
/* clearLongSelection(holder, position, alignParentRight,
data.get(position).getReceiverUserId().length() > 5); */
}
});
}
The code which I have commented in onCLick and onLongClick were used when the requirement was to select a single item.
these are the methods which were called in onClick and onLOngClick:
public boolean clearLongSelection(ViewHolder holder, int position) {
if (selectedPosition >= 0) {
if (selectedPosition == position) {
holder.parentLayout.setBackgroundResource(android.R.color.transparent);
if (alignParentRight) {
holder.mediaCardView.setBackgroundResource(android.R.color.white);
holder.assessmentCardView.setBackgroundResource(android.R.color.white);
holder.surveyCardView.setBackgroundResource(android.R.color.white);
holder.documentCardView.setBackgroundResource(android.R.color.white);
holder.textCardView.setBackgroundResource(android.R.color.white);
} else {
holder.mediaCardView.setBackgroundResource(R.color.long_press);
holder.assessmentCardView.setBackgroundResource(R.color.long_press);
holder.surveyCardView.setBackgroundResource(R.color.long_press);
holder.documentCardView.setBackgroundResource(R.color.long_press);
holder.textCardView.setBackgroundResource(R.color.long_press);
}
selectedPosition = -1;
invalidateOptionsMenu();
getSupportActionBar().setTitle(intentData.getName());
}
return true;
}
return false;
}
public void onLongClick(ViewHolder holder, int position) {
if (selectedPosition < 0) {
holder.parentLayout.setBackgroundResource(R.color.long_press);
holder.mediaCardView.setBackgroundResource(R.color.long_press);
holder.assessmentCardView.setBackgroundResource(R.color.long_press);
holder.surveyCardView.setBackgroundResource(R.color.long_press);
holder.documentCardView.setBackgroundResource(R.color.long_press);
holder.textCardView.setBackgroundResource(R.color.long_press);
selectedPosition = position;
invalidateOptionsMenu();
getSupportActionBar().setTitle("1 Selected");
} else {
}
}
The variable selectedPosition in onClick and clearLongSelection is initialised in the class as instance variable- selectedPosition = -1.
Use SparseBooleanArray to keep track of selected items in recycler view adapter
Initialize the SparseBooleanArray as private memeber variable
private SparseBooleanArray mClickedItems=new SparseBooleanArray();
Then inside your click function while clicking any item,store the clicked item position as true.
mClickedItems.put(getAdapterPosition(),true);
notifyDataSetChanged();
Then in the onBindViewHolder check if the position is already selected or not like this
if(mClickedItems.get(position)==true){
//Show selected color
}else {
//show unselected color
}
Hi everyone I'm stuck in this and need help :
Each item has a CheckBox and I set setOnLongClickListener for root element of my items in RecyclerView like this :
holder.faviorateVideoItemRelative.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View arg0) {
if (chk_visible)
{
return true ;
}
holder.chk_faviorateVideo.setChecked(!holder.chk_faviorateVideo.isChecked());
chk_visible = true ;
checkedItemsCNT = 1 ;
deleteListVideoCourses.add(data.get(holder.getAdapterPosition())) ;
notifyDataSetChanged() ;
return true ;
}
});
If I scroll down , when I make a long click on one of items , the CheckBox of wrong item get checked !
It because as you use RecycleView it reuse your view every time when you scroll. RecycleView reuse your resource like this
So when you scroll it's showing the wrong state of your view
Solution
If you write any logic for check-in onBindViewHolder then you have to use both part for true and false
if(yourCondition){
//code if condition is true
}else {
//code if condition is false
}
Other Solution
Simply you can solve it just using one statement to stop your RecycleView to reuse your view state like this
#Override
public void onBindViewHolder(ReqNotificationAdapter.MyViewHolder holder, int position) {
holder.setIsRecyclable(false);
//.................your other code
}
I use it to solve my problem.. hope it will solve yours if you don't have a problem stop Recycling with your purpose.
Could be an issue in your bind rather than setting of the value.
A common mistakes is not un-checking the view in the bind.
Make sure where you are setting checked, you have an else statement and set it to unchecked.
RecyclerView and Listview reuse views as they scroll, which includes any previously checked boxes. So it is important to un-check them if appropriate.
public void bindView(View view, ..... //varies on implementation. rough idea.
{
CheckBox mycheckbox = (CheckBox)view.findViewById(R.id.myidofcheckbox);
int pos = view.getPosition();
if(pos == 1) //example
mycheckbox.setChecked(true);
else
mycheckbox.setChecked(false);
Solution 1:
You can override two method getItemId, getItemViewType.
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
Like this:
public class EasyAdapter extends RecyclerView.Adapter<EasyAdapter.ViewHolder>{
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
}
Solution 2:
Set setIsRecyclable false.
EasyAdapter easyAdapter=new EasyAdapter();
easyAdapter.setIsRecyclable(false);
Yes it happens with ListView and RecyclerView
Try this code,
holder.faviorateVideoItemRelative.setTag(position);
holder.faviorateVideoItemRelative.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View arg0) {
int tempPos = (int)holder.faviorateVideoItemRelative.getTag();
if (chk_visible)
{
return true ;
}
if(!holder.chk_faviorateVideo.isChecked())
{
holder.chk_faviorateVideo.setChecked(true);
}
else
{
holder.chk_faviorateVideo.setChecked(false);
}
holder.chk_faviorateVideo.setChecked(!holder.chk_faviorateVideo.isChecked());
chk_visible = true ;
checkedItemsCNT = 1 ;
deleteListVideoCourses.add(data.get(tempPos)) ;
notifyDataSetChanged() ;
return true ;
}
});
Hope it will help you.
When you initialize your OnLongClickListener, it is reused in views when they are no longer visible because they are cached.
To solve the worry, create a new class to explicitly link an object to a listener and not just the view.
For example :
private class BufferVideoLongClickListener implements View.OnLongClickListener {
private VideoObject video; // And other stuff like checked, etc
BufferVideoLongClickListener(VideoObject video, ...) {
this.video = video;
...
}
#Override
public void onLongClick(View view) {
// Do your check and other things
if(checked)
...
}
}
And in your onBindViewHolder :
holder.faviorateVideoItemRelative.setOnLongClickListener(new BufferVideoLongClickListener(video, ...));
After using the above mentioned solutions,
The following solutions worked like a charm for me.
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
using holder.setIsRecyclable(false) removes the desired selection as well when you come back to it after the whole scrolling process.
I am creating a list of cards to display using the RecyclerView, where each card has a button to remove that card from the list.
When i use notifyItemRemoved() to remove the card in the RecyclerView, it removes the item and animates fine but the data in the list is not updated correctly.
If instead of that, i switch to the notifyDataSetChanged() then the items in list are removed and updated correctly, but then the cards dont animate.
Does someone has any experience in using the notifyItemRemoved() and know why it behaves differently than notifyDataSetChanged?
Here is some peiece of code that i am using:
private List<DetectedIssue> issues = new ArrayList<DetectedIssue>();
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
if(position >0){
RiskViewHolder riskHolder = (RiskViewHolder)holder;
final int index = position - 1;
final DetectedIssue anIssue = issues.get(index);
riskHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
int index = issues.indexOf(anIssue);
issues.remove(anIssue);
notifyItemRemoved(index);
//notifyDataSetChanged();
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public int getItemCount() {
return (issues.size()+1);
}
Use notifyItemRangeChanged(position, getItemCount()); after notifyItemRemoved(position);
You don't need to use index, just use position. See code below.
private List<DetectedIssue> issues = new ArrayList<DetectedIssue>();
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
if(position >0){
RiskViewHolder riskHolder = (RiskViewHolder)holder;
riskHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
issues.remove(position);
notifyItemRemoved(position);
//this line below gives you the animation and also updates the
//list items after the deleted item
notifyItemRangeChanged(position, getItemCount());
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public int getItemCount() {
return issues.size();
}
Tried
public void removeItem(int position) {
this.taskLists.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, getItemCount() - position);
}
and working like a charm.
my mistake ,
notifyItemChanged(position) is helpless,the item of position can be removed ,and the item of position+1 is fine,but the items start from position+2,you will get an Exception, please use notifyItemRangeChanged(position,getItemCount());
after notifyItemRemoved(position);
like this:
public void removeData(int position) {
yourdatalist.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,getItemCount());
}
Use this it is working perfectly.
issues.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, issues.size());
As #pskink suggested it was supposed to be (index+1) in my case with notifyItemRemoved(index+1), probably because i am reserving the top index i.e. position=0 for a header.
**my solution looks like this**
this way is unnecessary to use the heavy method:
//notifyItemRangeChanged(xx,xx)
/**
*
* recyclerView的item中的某一个view,获取其最外层的viewParent,也就是item对应的layout在adapter中的position
*
* #param recyclerView
* #param view:can be the deep one inside the item,or the item itself .
* #return
*/
public static int getParentAdapterPosition(RecyclerView recyclerView, View view, int parentId) {
if (view.getId() == parentId)
return recyclerView.getChildAdapterPosition(view);
View viewGroup = (View) view.getParent();
if (viewGroup != null && viewGroup.getId() == parentId) {
return recyclerView.getChildAdapterPosition(viewGroup);
}
//recursion
return getParentAdapterPosition(recyclerView, viewGroup, parentId);
}
//wherever you set the clickListener .
holder.setOnClickListener(R.id.rLayout_device_item, deviceItemClickListener);
holder.setOnLongClickListener(R.id.rLayout_device_item, deviceItemLongClickListener);
#Override
public boolean onLongClick(View v) {
final int position = ViewUtils.getParentAdapterPosition(rVDevicesList, v, R.id.rLayout_device_item);
return true;
}
In my case I use Content Provider and a Custom RecyclerView Adapter with Cursor. This line of code is where you notify:
getContext().getContentResolver().notifyChange(uri, null);
Assuming In your recyclerView adapter (Delete Button):
Uri currentUri = ContentUris.withAppendedId(DatabaseContract.ToDoEntry.CONTENT_URI_TODO, id);
int rowsDeleted = mContext.getContentResolver().delete(currentUri, null, null);
if (rowsDeleted == 0) {
Log.d(TAG, "onClick: Delete failed");
} else {
Log.d(TAG, "onClick: Delete Successful");
}
And in your Database Provider:
case TODO_ID:
selection = DatabaseContract.ToDoEntry._ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
rowsDeleted = database.delete(DatabaseContract.ToDoEntry.TODO_TABLE_NAME, selection, selectionArgs);
if (rowsDeleted != 0){
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsDeleted;
You can use getAdapterPosition() from the RecyclerView.ViewHolder
getLayoutPosition() provides the exact position of item in the layout and code is
holder.removeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Position for remove
int modPosition= holder.getAdapterPosition();
//remove item from dataset
numbers.remove(modPosition);
//remove item from recycler view
if(numbers.isEmpty())
notifyDataSetChanged ()
else
notifyItemRemoved(modPosition);
}
});
I thought they were the same, but they're not. The following code gives an indexOutOfBounds exception when I try to access the "position" index of my dataset, in this case a list of a model I created called Task:
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> {
private List<Task> taskList;
private TaskAdapter thisAdapter = this;
// cache of views to reduce number of findViewById calls
public static class TaskViewHolder extends RecyclerView.ViewHolder {
protected TextView taskTV;
protected ImageView closeBtn;
public TaskViewHolder(View v) {
super(v);
taskTV = (TextView)v.findViewById(R.id.taskDesc);
closeBtn = (ImageView)v.findViewById(R.id.xImg);
}
}
public TaskAdapter(List<Task> tasks) {
if(tasks == null)
throw new IllegalArgumentException("tasks cannot be null");
taskList = tasks;
}
// onBindViewHolder binds a model to a viewholder
#Override
public void onBindViewHolder(TaskViewHolder taskViewHolder, int pos) {
final int position = pos;
Task currTask = taskList.get(pos);
taskViewHolder.taskTV.setText(currTask.getDescription());
**taskViewHolder.closeBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("TRACE", "Closing task at position " + position);
// delete from SQLite DB
Task taskToDel = taskList.get(position);
taskToDel.delete();
// updating UI
taskList.remove(position);
thisAdapter.notifyItemRemoved(position);
}
});**
}
#Override
public int getItemCount() {
//Log.d("TRACE", taskList.size() + " tasks in DB");
return taskList.size();
}
// inflates row to create a viewHolder
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
View itemView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.list_item, parent, false);
Task currTask = taskList.get(pos);
//itemView.setBackgroundColor(Color.parseColor(currTask.getColor()));
return new TaskViewHolder(itemView);
}
}
Deleting from my recyclerview gives unexpected results sometimes. Sometimes the element ahead of the one clicked is deleted, other times an indexOutOfBounds exception occurs at "taskList.get(position)".
Reading https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html and https://developer.android.com/training/material/lists-cards.html did not give me any more insight into why this was happening and how to fix it.
It looks like RecyclerView recycles the rows, but I wouldn't expect an indexoutofbounds exception using a smaller subset of numbers to index my list.
RecyclerView does not rebind views when their positions change (for obvious performance reasons).
For example, if your data set looks like this:
A B C D
and you add item X via
mItems.add(1, X);
notifyItemInserted(1, 1);
to get
A X B C D
RecyclerView will only bind X and run the animation.
There is a getPosition method in ViewHolder but that may not match adapter position if you call it in the middle of an animation.
If you need the adapter position, your safest option is getting the position from the Adapter.
update for your comment
Add a Task field to the ViewHolder.
Change onCreateViewHolder as follows to avoid creating a listener object on each rebind.
// inflates row to create a viewHolder
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int type) {
View itemView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.list_item, parent, false);
final TaskViewHolder vh = new TaskViewHolder(itemView);
taskViewHolder.closeBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// delete from SQLite DB
Task taskToDel = vh.getTask();
final int pos = taskList.indexOf(taskToDel);
if (pos == -1) return;
taskToDel.delete();
// updating UI
taskList.remove(pos);
thisAdapter.notifyItemRemoved(pos);
}
});
}
so in your on bind method, you do
// onBindViewHolder binds a model to a viewholder
#Override
public void onBindViewHolder(TaskViewHolder taskViewHolder, int pos) {
Task currTask = taskList.get(pos);
taskViewHolder.setTask(currTask);
taskViewHolder.taskTV.setText(currTask.getDescription());
}
Like yigit said, RecyclerView works like that:
A B C D
and you add item X via
mItems.add(1, X);
notifyItemInserted(1, 1);
you get
A X B C D
Using holder.getAdapterPosition() in onClickListener() will give you the right item from dataset to be removed, not the "static" view position. Here's the doc about it onBindViewHolder
Why dont you use a public interface for the button click and controle the action in the MainActivity.
In your adapter add:
public interface OnItemClickListener {
void onItemClick(View view, int position, List<Task> mTaskList);
}
and
public OnItemClickListener mItemClickListener;
// Provide a suitable constructor (depends on the kind of dataset)
public TaskAdapter (List<Task> myDataset, OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
this.mDataset = mDataset;
}
plus the call in the ViewHolder class
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(View v) {
super(v);
...
closeBtn = (ImageView)v.findViewById(R.id.xImg);
closeBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// If not long clicked, pass last variable as false.
mItemClickListener.onItemClick(v, getAdapterPosition(), mDataset);
}
}
In your MainActivity change your adapter to handle the call
// set Adapter
mAdapter = new TaskAdapter(taskList, new TaskAdapter.OnItemClickListener() {
#Override
public void onItemClick(View v, int position) {
if (v.getId() == R.id.xImg) {
Task taskToDel = taskList.get(position);
// updating UI
taskList.remove(position);
thisAdapter.notifyItemRemoved(position);
// remove from db with unique id to use delete query
// dont use the position but something like taskToDel.getId()
taskToDel.delete();
}
}
});
Thanks to #yigit for his answer, his solution mainly worked, I just tweaked it a little bit so as to avoid using vh.getTask() which I was not sure how to implement.
final ViewHolder vh = new ViewHolder(customView);
final KittyAdapter final_copy_of_this = this;
// We attach a CheckChange Listener here instead of onBindViewHolder
// to avoid creating a listener object on each rebind
// Note Rebind is only called if animation must be called on view (for efficiency)
// It does not call on the removed if the last item is checked
vh.done.setChecked(false);
vh.done.setOnCheckedChangeListener(null);
vh.done.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
buttonView.setEnabled(false);
final int pos2 = vh.getAdapterPosition(); // THIS IS HOW TO GET THE UPDATED POSITION
// YOU MUST UPDATE THE DATABASE, removed by Title
DatabaseHandler db = new DatabaseHandler(mContext);
db.remove(mDataSet.get(pos2).getTitle(), fp);
db.close();
// Update UI
mDataSet.remove(pos2);
final_copy_of_this.notifyItemRemoved(pos2);
}
});
Notice instead to get the updated position, you can call vh.getAdapterPosition(), which is the line that will give you the updated position from the underlying dataset rather than the fake view.
This is working for me as of now, if someone knows of a drawback to using this please let me know. Hope this helps someone.
Personally, I don't like this concept of RecyclerViews. Seems like it wasn't thought of completely.
As it was said when removing an item the Recycler view just hides an item. But usually you don't want to leave that item in your collection. When deleting an item from the collection "it shifts its elements towards 0" whereas recyclerView keeps the same size.
If you are calling taskList.remove(position); your position must be evaluated again:
int position = recyclerView.getChildAdapterPosition(taskViewHolder.itemView);