333

Trying to figure out what is the issue with updating RecyclerView's Adapter.

After I get a new List of products, I tried to:

  1. Update the ArrayList from the fragment where recyclerView is created, set new data to adapter, then call adapter.notifyDataSetChanged() ; it did not work.

  2. Create a new adapter, as others did, and it worked for them, but no change for me: recyclerView.setAdapter(new RecyclerViewAdapter(newArrayList))

  3. Create a method in Adapter which updates the data as follows:

    public void updateData(ArrayList<ViewModel> viewModels) {
       items.clear();
       items.addAll(viewModels);
       notifyDataSetChanged();
    }
    

    Then I call this method whenever I want to update the data list; it did not work.

  4. To check if I can modify the recyclerView in any way, and I tried to remove at least an item:

     public void removeItem(int position) {
        items.remove(position);
        notifyItemRemoved(position);
    }
    

    Everything remained as it was.

Here is my Adapter:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements View.OnClickListener {

    private ArrayList<ViewModel> items;
    private OnItemClickListener onItemClickListener;

    public RecyclerViewAdapter(ArrayList<ViewModel> items) {
        this.items = items;
    }


    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false);
        v.setOnClickListener(this);
        return new ViewHolder(v);
    }

    public void updateData(ArrayList<ViewModel> viewModels) {
        items.clear();
        items.addAll(viewModels);
        notifyDataSetChanged();
    }
    public void addItem(int position, ViewModel viewModel) {
        items.add(position, viewModel);
        notifyItemInserted(position);
    }

    public void removeItem(int position) {
        items.remove(position);
        notifyItemRemoved(position);
    }



    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        ViewModel item = items.get(position);
        holder.title.setText(item.getTitle());
        Picasso.with(holder.image.getContext()).load(item.getImage()).into(holder.image);
        holder.price.setText(item.getPrice());
        holder.credit.setText(item.getCredit());
        holder.description.setText(item.getDescription());

        holder.itemView.setTag(item);
    }

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

    @Override
    public void onClick(final View v) {
        // Give some time to the ripple to finish the effect
        if (onItemClickListener != null) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    onItemClickListener.onItemClick(v, (ViewModel) v.getTag());
                }
            }, 0);
        }
    }

    protected static class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView image;
        public TextView price, credit, title, description;

        public ViewHolder(View itemView) {
            super(itemView);
            image = (ImageView) itemView.findViewById(R.id.image);
            price = (TextView) itemView.findViewById(R.id.price);
            credit = (TextView) itemView.findViewById(R.id.credit);
            title = (TextView) itemView.findViewById(R.id.title);
            description = (TextView) itemView.findViewById(R.id.description);
        }
    }

    public interface OnItemClickListener {

        void onItemClick(View view, ViewModel viewModel);

    }
}

And I initiate RecyclerView as follows:

recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 5));
adapter = new RecyclerViewAdapter(items);
adapter.setOnItemClickListener(this);
recyclerView.setAdapter(adapter);

So, how do I actually update adapter data in order to display newly received items?


Update: the issue was that the layout where gridView was looked as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:tag="catalog_fragment"
    android:layout_height="match_parent">

    <FrameLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"/>

        <ImageButton
            android:id="@+id/fab"
            android:layout_gravity="top|end"
            style="@style/FabStyle"/>

    </FrameLayout>
</LinearLayout>

Then I just removed LinearLayout and made FrameLayout as parent layout.

Filip Luchianenco
  • 6,614
  • 8
  • 38
  • 58
  • 1
    `items.clear(); items.addAll(newItems);` is an ugly pattern. If you really need defensive copying here, `items = new ArrayList(newItems);` would be less ugly. – Miha_x64 Oct 18 '18 at 09:37
  • 2
    @miha-x64 You're right - it would be less ugly. The problem is that this just don't work. The adapter gets no reference to the reference. It gets the reference itself. So if you build a new dataset it has a new reference while the adapter still only knows the old one. – The incredible Jan Feb 22 '19 at 12:53

13 Answers13

409

This is a general answer for future visitors. The various ways to update the adapter data are explained. The process includes two main steps every time:

  1. Update the data set
  2. Notify the adapter of the change

#Insert single item

Add "Pig" at index 2.

Insert single item
String item = "Pig";
int insertIndex = 2;
data.add(insertIndex, item);
adapter.notifyItemInserted(insertIndex);

#Insert multiple items

Insert three more animals at index 2.

Insert multiple items
ArrayList<String> items = new ArrayList<>();
items.add("Pig");
items.add("Chicken");
items.add("Dog");
int insertIndex = 2;
data.addAll(insertIndex, items);
adapter.notifyItemRangeInserted(insertIndex, items.size());

#Remove a single item

Remove "Pig" from the list.

Remove single item
int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);

#Remove multiple items

Remove "Camel" and "Sheep" from the list.

Remove multiple items
int startIndex = 2; // inclusive
int endIndex = 4;   // exclusive
int count = endIndex - startIndex; // 2 items will be removed
data.subList(startIndex, endIndex).clear();
adapter.notifyItemRangeRemoved(startIndex, count);

#Remove all items

Clear the whole list.

Remove all items
data.clear();
adapter.notifyDataSetChanged();

#Replace old list with the new list

Clear the old list then add a new one.

Replace old list with new list
// clear old list
data.clear();

// add new list
ArrayList<String> newList = new ArrayList<>();
newList.add("Lion");
newList.add("Wolf");
newList.add("Bear");
data.addAll(newList);

// notify adapter
adapter.notifyDataSetChanged();

The adapter has a reference to data, so it is important that I didn't set data to a new object. Instead, I cleared the old items from data and then added the new ones.

#Update single item

Change the "Sheep" item so that it says "I like sheep."

Update single item
String newValue = "I like sheep.";
int updateIndex = 3;
data.set(updateIndex, newValue);
adapter.notifyItemChanged(updateIndex);

#Move single item

Move "Sheep" from position 3 to position 1.

Move single item
int fromPosition = 3;
int toPosition = 1;

// update data array
String item = data.get(fromPosition);
data.remove(fromPosition);
data.add(toPosition, item);

// notify adapter
adapter.notifyItemMoved(fromPosition, toPosition);

#Code

Here is the project code for your reference. The RecyclerView Adapter code can be found at this answer.

MainActivity.java

public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {

    List<String> data;
    MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // data to populate the RecyclerView with
        data = new ArrayList<>();
        data.add("Horse");
        data.add("Cow");
        data.add("Camel");
        data.add("Sheep");
        data.add("Goat");

        // set up the RecyclerView
        RecyclerView recyclerView = findViewById(R.id.rvAnimals);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
                layoutManager.getOrientation());
        recyclerView.addItemDecoration(dividerItemDecoration);
        adapter = new MyRecyclerViewAdapter(this, data);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
    }

    public void onButtonClick(View view) {
        insertSingleItem();
    }

    private void insertSingleItem() {
        String item = "Pig";
        int insertIndex = 2;
        data.add(insertIndex, item);
        adapter.notifyItemInserted(insertIndex);
    }

    private void insertMultipleItems() {
        ArrayList<String> items = new ArrayList<>();
        items.add("Pig");
        items.add("Chicken");
        items.add("Dog");
        int insertIndex = 2;
        data.addAll(insertIndex, items);
        adapter.notifyItemRangeInserted(insertIndex, items.size());
    }

    private void removeSingleItem() {
        int removeIndex = 2;
        data.remove(removeIndex);
        adapter.notifyItemRemoved(removeIndex);
    }

    private void removeMultipleItems() {
        int startIndex = 2; // inclusive
        int endIndex = 4;   // exclusive
        int count = endIndex - startIndex; // 2 items will be removed
        data.subList(startIndex, endIndex).clear();
        adapter.notifyItemRangeRemoved(startIndex, count);
    }

    private void removeAllItems() {
        data.clear();
        adapter.notifyDataSetChanged();
    }

    private void replaceOldListWithNewList() {
        // clear old list
        data.clear();

        // add new list
        ArrayList<String> newList = new ArrayList<>();
        newList.add("Lion");
        newList.add("Wolf");
        newList.add("Bear");
        data.addAll(newList);

        // notify adapter
        adapter.notifyDataSetChanged();
    }

    private void updateSingleItem() {
        String newValue = "I like sheep.";
        int updateIndex = 3;
        data.set(updateIndex, newValue);
        adapter.notifyItemChanged(updateIndex);
    }

    private void moveSingleItem() {
        int fromPosition = 3;
        int toPosition = 1;

        // update data array
        String item = data.get(fromPosition);
        data.remove(fromPosition);
        data.add(toPosition, item);

        // notify adapter
        adapter.notifyItemMoved(fromPosition, toPosition);
    }
}

#Notes

  • If you use notifyDataSetChanged(), then no animation will be performed. This can also be an expensive operation, so it is not recommended to use notifyDataSetChanged() if you are only updating a single item or a range of items.
  • Check out DiffUtil if you are making large or complex changes to a list.

#Further study

Rahul
  • 2,374
  • 2
  • 22
  • 36
Suragch
  • 364,799
  • 232
  • 1,155
  • 1,198
  • 5
    Awesome answer! What would be the steps when replacing a in item, which would result in a different view type? Is it just notifyItemChanged or a combined remove followed by an insert? – Semaphor Sep 25 '18 at 07:11
  • With your minimal example, it looks like notifyItemChanged is sufficient. It will call onCreateViewHolder and onBindViewHolder for the changed item and the different view is shown. I had a problem in an application updating an item which would result in a different view, but there seems to be another problem. – Semaphor Oct 01 '18 at 14:43
  • @Suragch any idea about my question : https://stackoverflow.com/questions/57332222/how-do-i-update-my-recycleview-button-state-on-click-after-alertdialog-confirmat/57333319?noredirect=1#comment101161176_57333319 I tried everything listed in this thread but to no avail :( –  Aug 04 '19 at 11:52
  • How about when we use DiffUtils to make changes? They are not so fluid like calling manually .notify(). – GuilhE Mar 19 '20 at 11:13
  • 2
    **This is the best answer in a history of answers, maybe ever.** – Firzen Apr 17 '20 at 07:56
  • 1
    Really dropped the ball under `Update single item`, should have been **I like turtles** – ardnew May 02 '20 at 02:52
  • Have you or has someone updated this answer for Kotlin? – Zonker.in.Geneva May 30 '20 at 11:48
  • @Zonker.in.Geneva, I haven't but I would welcome someone to add a Kotlin version. – Suragch May 31 '20 at 02:52
  • Why replacing old list with new list for completely dataset updating? Isn't it a performance issue? – ATES Jun 21 '20 at 13:38
  • @ATES, I never noticed a performance issue, but I probably never had a list longer than 100 items, either. – Suragch Jun 22 '20 at 00:20
  • Hi, I'm still a newbie. Is there a way to update the index that's displayed on the View? My problem is that I have to display the index of each item in the RecyclerView. So, when I do a remove or insert, the indices aren't updating, e.g. I have a list of `{"one", "two", "three", "four"}` and I do a remove at index `1` (contains element `two`), what I want is RecyclerView to update the View that's displaying the index of element `three`, `four`, ..., accordingly. Here's what I don't want to happen: https://i.imgur.com/rLjyp1W.png – LuckMan Nov 28 '20 at 01:43
  • cont. I can achieve it by using the `notifyDataSetChanged` method, but it removes the animation, and I want to keep the animation. – LuckMan Nov 28 '20 at 01:52
  • 1
    @LuckMan, I'd recommend asking this as a new question. I'm mostly working with Flutter now so I've kind of forgotten about the details of how to do Android development. – Suragch Nov 28 '20 at 06:24
  • Never mind. I managed to do it using `notifyItemRangeChanged`. – LuckMan Nov 28 '20 at 11:36
  • Came across with your answer and it worked. Thanks a lot! – no_profile Mar 13 '21 at 14:45
370

I'm working with RecyclerView and both the remove and the update work well.

1) REMOVE: There are 4 steps to remove an item from a RecyclerView

list.remove(position);
recycler.removeViewAt(position);
mAdapter.notifyItemRemoved(position);                 
mAdapter.notifyItemRangeChanged(position, list.size());

These line of codes work for me.

2) UPDATE THE DATA: The only things I had to do is

mAdapter.notifyDataSetChanged();

You had to do all of this in the Actvity/Fragment code not in the RecyclerView Adapter code.

CaptJak
  • 3,542
  • 1
  • 25
  • 48
Niccolò Passolunghi
  • 5,608
  • 2
  • 24
  • 33
  • 2
    Thank you. Please check the update. Somehow, linear layout does not let the RecylerView update list. – Filip Luchianenco Jul 12 '15 at 14:44
  • 55
    you only need these two lines: list.remove(position); mAdapter.notifyItemRemoved(position); – feisal Mar 10 '16 at 20:00
  • 4
    For me, the lines `recycler.removeViewAt(position);` (or rather `recycler.removeAllViews()`) were the crucial ones. – MSpeed Mar 16 '16 at 11:20
  • 1
    I use list.remove(position), followed by notifyDataSetChanged and it seems to do the trick – Lion789 Apr 26 '16 at 16:33
  • I am using viewholder and when using viewholder for recycler view adapter, we can simply use `notifyDataSetChanged()` inside `onBindViewHolder()` after our events fire. Hope it helps someone. – 89n3ur0n May 07 '16 at 18:40
  • 3
    An important consideration to avoid annoying glitch during the delete: You don't need to call this line recycler.removeViewAt(position); – Angelo Nodari Jul 15 '16 at 08:54
  • 13
    NotifyDataSetChanged is overkill, specially if you are dealing with VERY long lists. Reload the whole thing for a few items? No, thanks. Also, recycler.removeViewAt(position)? Not needed. And don't need to call both "mAdapter.notifyItemRemoved(position)" and "mAdapter.notifyItemRangeChanged(position, list.size())". Remove some, or remove one. Notify ONCE. Call one of them. – Vitor Hugo Schwaab Dec 11 '16 at 17:41
  • 2
    recyclerview gives a nice default animation of removing and moving items when using `notifyItemRemoved` and `notifyItemMoved`. By using `notifyDataSetChanged` you lose that animation. :( – Thupten Dec 31 '16 at 21:10
  • please remove recycler.removeViewAt(position); – Ahamadullah Saikat Nov 11 '17 at 16:58
  • 1
    From the docs: "f you are writing an adapter it will always be more efficient to use the more specific change events if you can. Rely on notifyDataSetChanged() as a last resort." Source - https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter#notifyDataSetChanged() – Mark Lapasa Nov 18 '18 at 15:39
  • Out in the Real World, there are plenty of cases where the client doesn't know about individual changes are only gets a message to replace all of the data. – Jeffrey Blattman Jun 04 '19 at 20:27
  • @nicopasso any idea about my question, i tried everything listed here but no luck : https://stackoverflow.com/questions/57332222/how-do-i-update-my-recycleview-button-state-on-click-after-alertdialog-confirmat/57333319?noredirect=1#comment101161176_57333319 –  Aug 04 '19 at 11:51
  • Just to correct list don't have remove method which take position directly. It either by RemoveAt(position) or remove(item). Also after delete item you got error for this line recycler.removeViewAt(position); So it need to remove. – Mohit Dixit Jul 31 '20 at 13:28
  • @feisal you are right, but I still can't understand how this works ! I mean, how the adapter uses `list` after an item is removed from it, is still unclear to me. Things get wore for me when it comes to notifyItemInserted and notifyItemChanged. Can someone please explain ? – YoussefDir Oct 13 '20 at 12:42
50

This is what worked for me:

recyclerView.setAdapter(new RecyclerViewAdapter(newList));
recyclerView.invalidate();

After creating a new adapter that contains the updated list (in my case it was a database converted into an ArrayList) and setting that as adapter, I tried recyclerView.invalidate() and it worked.

Martin
  • 790
  • 6
  • 14
  • 14
    wouldn't this refresh the entire view instead of just updating the items that have changed? – TWilly Feb 25 '16 at 18:44
  • 17
    Instead of making a new adapter each time, what I did was to create a setter method in my custom adapter class to set the new list. After that, just call `YourAdapter adapter = (YourAdapter) recyclerView.getAdapter(); adapter.yourSetterMethod(newList); adapter.notifyDataSetChanged();` That being said, it sounds like what the OP tried first (just adding this on as a comment so that it may help someone else, as that worked in my case). – Kevin Lee Apr 15 '16 at 11:50
  • 3
    Reader, don't settle for this. This answer works, but there's a more efficient way. Instead of reloading *all data again*, the most efficient way is just add the new data to the adapter. – Sebastialonso Aug 15 '16 at 03:30
  • 1
    Yes I agree with @TWilly it will redraw complete View on UI. – Rahul Aug 24 '17 at 17:47
18

you have 2 options to do this: refresh UI from the adapter:

mAdapter.notifyDataSetChanged();

or refresh it from recyclerView itself:

recyclerView.invalidate();
ediBersh
  • 1,025
  • 1
  • 12
  • 17
15

Another option is to use diffutil . It will compare the original list against the new list and use the new list as the update if there is a change.

Basically, we can use DiffUtil to compare the old data vs new data and let it call notifyItemRangeRemoved, and notifyItemRangeChanged and notifyItemRangeInserted on your behalf.

A quick example of using diffUtil instead of notifyDataSetChanged:

DiffResult diffResult = DiffUtil
                .calculateDiff(new MyDiffUtilCB(getItems(), items));

//any clear up on memory here and then
diffResult.dispatchUpdatesTo(this);

//and then, if necessary
items.clear()
items.addAll(newItems)

I do the calculateDiff work off the main thread in case it's a big list.

MatPag
  • 29,651
  • 11
  • 74
  • 87
j2emanue
  • 51,417
  • 46
  • 239
  • 380
  • 1
    although this is correct, how do update the data inside your adapter? Let's say I am displaying List in the adapter and I get a new update with List. DiffUtil will calculate a difference and dispatches it in the adapter, but it is doing nothing with the original or new list (in your case `getItems()`. How do you know which data from original list need to be removed/added/updated? – vanomart Jan 12 '17 at 10:17
  • 2
    Maybe this article can help. .. https://medium.com/@nullthemall/diffutil-is-a-must-797502bc1149#.9e7v4tsv8 – j2emanue Jan 12 '17 at 13:25
  • @vanomart you only have to directly replace your local list field with the new list value as you would normally do, the only difference in this approach is that instead of notifyDataSetChanged() you use DiffUtil to update the view. – carrizo Mar 06 '17 at 03:24
  • any idea about mine ? i tried everything listed here but no luck : https://stackoverflow.com/questions/57332222/how-do-i-update-my-recycleview-button-state-on-click-after-alertdialog-confirmat/57333319?noredirect=1#comment101161176_57333319 –  Aug 04 '19 at 11:51
  • Thank you for your answer! Can you please explain why I should put the "clear" & "addAll" after the dispatchUpdatesTo?? Tnx! – Adi Azarya Mar 22 '20 at 09:38
  • it was just an example, you can ignore it or search the web how to use it. i was just making a quick example – j2emanue Mar 23 '20 at 01:14
10

Update Data of listview, gridview and recyclerview

mAdapter.notifyDataSetChanged();

or

mAdapter.notifyItemRangeChanged(0, itemList.size());
Pankaj Talaviya
  • 2,693
  • 22
  • 29
  • This doesn't seem to update my data until the user starts scrolling. I've looked all over the place and can't figure why.. – SudoPlz Mar 19 '18 at 16:35
  • @SudoPlz you can use custom scroll listener for detect scroll and perform your notify operation like https://stackoverflow.com/a/31174967/4401692 – Pankaj Talaviya Mar 20 '18 at 04:21
  • Thanks Pankaj but that's exactly what I'm trying to avoid. I want to update everything WITHOUT having the user touch the screen. – SudoPlz Mar 20 '18 at 10:18
5

The best and the coolest way to add new data to the present data is

 ArrayList<String> newItems = new ArrayList<String>();
 newItems = getList();
 int oldListItemscount = alcontainerDetails.size();
 alcontainerDetails.addAll(newItems);           
 recyclerview.getAdapter().notifyItemChanged(oldListItemscount+1, al_containerDetails);
CoDe
  • 10,214
  • 14
  • 74
  • 180
Rushi Ayyappa
  • 2,620
  • 2
  • 13
  • 26
  • 2
    I see people using the "notifyDataSetChanged" for EVERYthing, isn't that overkill? I mean, reload the whole list because a few changed or were added... I like this approach, was implementing right now, with the "notifyItemRangeInserted" method. – Vitor Hugo Schwaab Dec 11 '16 at 17:37
5

I've solved the same problem in a different way. I don't have data I waiting for it from the background thread so start with an emty list.

        mAdapter = new ModelAdapter(getContext(),new ArrayList<Model>());
   // then when i get data

        mAdapter.update(response.getModelList());
  //  and update is in my adapter

        public void update(ArrayList<Model> modelList){
            adapterModelList.clear(); 
            for (Product model: modelList) {
                adapterModelList.add(model); 
            }
           mAdapter.notifyDataSetChanged();
        }

That's it.

Ahmed Ozmaan
  • 148
  • 3
  • 6
  • I don't get ist. Your code doesn't make any sense to me. Why should you loop over a list to add it's items to another list? And why ist the class "Product" compatible to "Model". Why not just call "mAdapter = new ModelAdapter(getContext(),response.getModelList());" or copy the list from response at once? – The incredible Jan May 14 '21 at 13:53
3

I found out that a really simple way to reload the RecyclerView is to just call

recyclerView.removeAllViews();

This will first remove all content of the RecyclerView and then add it again with the updated values.

2

These methods are efficient and good to start using a basic RecyclerView.

private List<YourItem> items;

public void setItems(List<YourItem> newItems)
{
    clearItems();
    addItems(newItems);
}

public void addItem(YourItem item, int position)
{
    if (position > items.size()) return;

    items.add(item);
    notifyItemInserted(position);
}

public void addMoreItems(List<YourItem> newItems)
{
    int position = items.size() + 1;
    newItems.addAll(newItems);
    notifyItemChanged(position, newItems);
}

public void addItems(List<YourItem> newItems)
{
    items.addAll(newItems);
    notifyDataSetChanged();
}

public void clearItems()
{
    items.clear();
    notifyDataSetChanged();
}

public void addLoader()
{
    items.add(null);
    notifyItemInserted(items.size() - 1);
}

public void removeLoader()
{
    items.remove(items.size() - 1);
    notifyItemRemoved(items.size());
}

public void removeItem(int position)
{
    if (position >= items.size()) return;

    items.remove(position);
    notifyItemRemoved(position);
}

public void swapItems(int positionA, int positionB)
{
    if (positionA > items.size()) return;
    if (positionB > items.size()) return;

    YourItem firstItem = items.get(positionA);

    videoList.set(positionA, items.get(positionB));
    videoList.set(positionB, firstItem);

    notifyDataSetChanged();
}

You can implement them inside of an Adapter Class or in your Fragment or Activity but in that case you have to instantiate the Adapter to call the notification methods. In my case I usually implement it in the Adapter.

Teocci
  • 4,348
  • 1
  • 34
  • 36
1

i got the answer after a long time

  SELECTEDROW.add(dt);
                notifyItemInserted(position);
                SELECTEDROW.remove(position);
                notifyItemRemoved(position);
roufal
  • 11
  • 1
1

I strongly recommend you to use [DiffUtil.ItemCallback][1] to handle the change in RecyclerView.Adapter


 fun setData(data: List<T>) {
        val calculateDiff = DiffUtil.calculateDiff(DiffUtilCallback(items, data))
        items.clear()
        items += data
        calculateDiff.dispatchUpdatesTo(this)
    }

under the hood it handles most of the things with AdapterListUpdateCallback:

/**
 * ListUpdateCallback that dispatches update events to the given adapter.
 *
 * @see DiffUtil.DiffResult#dispatchUpdatesTo(RecyclerView.Adapter)
 */
public final class AdapterListUpdateCallback implements ListUpdateCallback {
    @NonNull
    private final RecyclerView.Adapter mAdapter;

    /**
     * Creates an AdapterListUpdateCallback that will dispatch update events to the given adapter.
     *
     * @param adapter The Adapter to send updates to.
     */
    public AdapterListUpdateCallback(@NonNull RecyclerView.Adapter adapter) {
        mAdapter = adapter;
    }

    /** {@inheritDoc} */
    @Override
    public void onInserted(int position, int count) {
        mAdapter.notifyItemRangeInserted(position, count);
    }

    /** {@inheritDoc} */
    @Override
    public void onRemoved(int position, int count) {
        mAdapter.notifyItemRangeRemoved(position, count);
    }

    /** {@inheritDoc} */
    @Override
    public void onMoved(int fromPosition, int toPosition) {
        mAdapter.notifyItemMoved(fromPosition, toPosition);
    }

    /** {@inheritDoc} */
    @Override
    public void onChanged(int position, int count, Object payload) {
        mAdapter.notifyItemRangeChanged(position, count, payload);
    }
}

ibrahimyilmaz
  • 16,643
  • 12
  • 56
  • 79
0

If nothing mentioned in the above comments is working for you. It might mean the problem lies somewhere else.

One place I found the solution was in the way I was setting the list to the adapter. In my activity the list was a instance variable and I was changing it directly when any data changed. Due to it being a reference variable there was something weird going on. So I changed the reference variable to a local one and used another variable to update data and then pass to addAll() function mentioned in above answers.

bitSmith
  • 11
  • 4