using notifyItemRemoved or notifyDataSetChanged with RecyclerView in Android

56,231

Solution 1

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.

Solution 2

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

Solution 3

Tried

public void removeItem(int position) {
    this.taskLists.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, getItemCount() - position);
}

and working like a charm.

Solution 4

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

Solution 5

Use this it is working perfectly.

        issues.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position, issues.size());
Share:
56,231
revolutionary
Author by

revolutionary

Updated on September 27, 2021

Comments

  • revolutionary
    revolutionary over 2 years

    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);
    }
    
  • Viral Patel
    Viral Patel over 8 years
    please provide details on what will change by doing this and how it will help resolve the issue.
  • Juan Cruz Soler
    Juan Cruz Soler over 7 years
    From documentation: "You should only use the position parameter while acquiring the related data item inside this method and should not keep a copy of it. If you need the position of an item later on (e.g. in a click listener), use RecyclerView.ViewHolder.getAdapterPosition() which will have the updated adapter position."
  • marcos E.
    marcos E. about 7 years
    You should use getAdapterPosition as the documentation states, you´re on risk of creating inconsistencies.
  • Yohan Dahmani
    Yohan Dahmani almost 7 years
    @Akshay Mahajan Old thread sorry, but notifyItemRemoved(position); works just fine alone (with animation). What notifyItemRangeChanged(position, getItemCount()); is doing ? I can't see the difference. Thank you
  • Michał Ziobro
    Michał Ziobro over 6 years
    Shouldn't be getItemCount() - position, as itemCount means the count of items after removed item?
  • Travis Castillo
    Travis Castillo over 6 years
    yes, the second parameter is range of changed items. using item count means that every item after the position is changing.
  • hamena314
    hamena314 about 6 years
    Could you explain why you use getItemCount() - position instead of just getItemCount()?
  • Bajrang Hudda
    Bajrang Hudda over 5 years
    @YohanDahmani, notifyItemRemoved(position); won't work if you are trying on last item..IndexOutOfBoundException you gonna get.
  • Jay
    Jay over 5 years
    @hamena314 actually notifyItemRangeChanged(int position, int itemCount) ment tha at "position" items have changed and from "position" , " itemCount" items have changed so it is wise that to pass only items after "positon" instead passing list of all the items. Or instead passing "getItemCount() - position" we can pass getItemCount().
  • Manuel
    Manuel almost 5 years
    This answer is nonsensical. Both notifyItemRemoved and notifyItemRangeChanged are doing the same thing. Why this answer has so many upvotes is a mystery.
  • ralphgabb
    ralphgabb over 3 years
    this worked. the position of the row object will also be updated.
  • Arbaz.in
    Arbaz.in about 3 years
    getting error while removing last element of array list using this notifyItemRemoved(last pos) any solution for same?
  • sree_sg
    sree_sg about 3 years
    can you check this? if(numbers.isEmpty()) notifyDataSetChanged () else notifyItemRemoved(modPosition);