65

I am trying to remove all the elements from my RecyclerView in my onRestart method so the items don't get loaded twice:

@Override
protected void onRestart() {
    super.onRestart();

    // first clear the recycler view so items are not populated twice
    for (int i = 0; i < recyclerAdapter.getSize(); i++) {
        recyclerAdapter.delete(i);
    }

    // then reload the data
    PostCall doPostCall = new PostCall(); // my AsyncTask... 
    doPostCall.execute();
}

But for some reason the delete method I created in the adapter is not functioning properly:

in RecyclerAdapter.java:

public void delete(int position){
    myList.remove(position);
    notifyItemRemoved(position);
}

public int getSize(){
    return myList.size();
}

I think every other item in my list gets deleted instead of the entire list.

With a listview it was so easy and I simply called adapter.clear().

Can someone please help me fix up the code?

I think I should be using notifyItemRangeRemoved(...,...); but I am not sure how. TIA

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
user2456977
  • 3,830
  • 14
  • 48
  • 87
  • BTW: you should be punished for not using `{` `}` around code blocks. One-liner code block is still code block. There shall be no exception – Marcin Orlowski Apr 30 '15 at 22:14
  • 1
    Ha I'm a noob. what do you expect -- better now ? :) – user2456977 Apr 30 '15 at 22:18
  • Yes, much better :) To find out why it's better to have good habits for you too, learn about programming languages that utilize preprocessor, like i.e. `C`. :) and what bugs this can easily bring for your "enjoyment" (just because you have no brackets :( – Marcin Orlowski Apr 30 '15 at 22:28
  • the people here made great points: http://programmers.stackexchange.com/questions/16528/single-statement-if-block-braces-or-no .... Although, this has not solved my original problem. Do you have any ideas? – user2456977 Apr 30 '15 at 22:31
  • I do not see much good points there. The less exceptions from your habbits you do, the better for you. So putting all in one line is silly excuse due to code formatting tools. For your original problem - I just wanted to comment lack of brackets, not solve your problem. Maybe others... – Marcin Orlowski Apr 30 '15 at 22:34
  • 1
    Haha Well you're no help – user2456977 Apr 30 '15 at 23:53

14 Answers14

85

This works great for me:

public void clear() {
    int size = data.size();
    if (size > 0) {
        for (int i = 0; i < size; i++) {
            data.remove(0);
        }

        notifyItemRangeRemoved(0, size);
    }
}

Source: https://github.com/mikepenz/LollipopShowcase/blob/master/app/src/main/java/com/mikepenz/lollipopshowcase/adapter/ApplicationAdapter.java

or:

public void clear() {
    int size = data.size();
    data.clear();
    notifyItemRangeRemoved(0, size);
}

For you:

@Override
protected void onRestart() {
    super.onRestart();

    // first clear the recycler view so items are not populated twice
    recyclerAdapter.clear();

    // then reload the data
    PostCall doPostCall = new PostCall(); // my AsyncTask... 
    doPostCall.execute();
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
  • 14
    in `clearData()`, why not simply do:`myList.clear()`? – kip2 Jul 13 '15 at 13:36
  • 5
    @kip2 there is no method `clear()` in `RecyclerView ` – oleynikd Mar 02 '16 at 23:29
  • @kip2 When I first implemented this, there was an issue with the `notifyItemRangeRemoved` and clearing at the same time. I simply check the size to make sure there is an item available. – Jared Burrows Mar 03 '16 at 03:35
  • 1
    @JaredBurrows gotcha. @oleynikd `clear()` is a `List` method, not the RecyclerView's. You could use it alongside/in place of Jared's answer in the `clearData()` method above – kip2 Mar 03 '16 at 09:19
  • I believe that the items are removed one at a time, and then notify is called so that removal animations can play for each. – Christopher Perry Jan 12 '17 at 19:48
  • May want to throw a null check on the list prior to the size method as it throws a null pointer. – Braden Holt Sep 07 '17 at 20:42
  • I got with a simple way, by running this: modelArrayList.clear(); markerAdapter.notifyDataSetChanged(); – Almeida Dec 17 '18 at 12:10
  • if you have Generic Array List use this: data.remove( data.get(i)); myRecAdapter.notifyDataSetChanged(); – Adil Siddiqui Mar 31 '20 at 03:45
  • Consistently facing `java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter position` issue with this approach. Hence resorted to using `notifyDataSetChanged()` – iCantC Jul 18 '21 at 08:22
77

Avoid deleting your items in a for loop and calling notifyDataSetChanged in every iteration. Instead just call the clear method in your list myList.clear(); and then notify your adapter

public void clearData() {
    myList.clear(); // clear list
    mAdapter.notifyDataSetChanged(); // let your adapter know about the changes and reload view.
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Bojan Kseneman
  • 15,488
  • 2
  • 54
  • 59
  • 1
    This notifies that the data has changed but does not animate the list. – Jared Burrows Mar 03 '16 at 03:36
  • notifyItemRangeChanged does -> https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemRangeChanged(int, int) – Bojan Kseneman Aug 21 '16 at 07:41
  • Thank you! This is also a solution for RecyclerView IndexOutOfBOundsException. – sHOLE Aug 02 '17 at 01:14
  • 2
    sometime i got exception when clear and add new items in recyclerview. java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter position ViewHolder – Ram Jan 19 '18 at 08:17
22
setAdapter(null);

Useful if RecycleView have different views type

Aksenov Vladimir
  • 677
  • 1
  • 6
  • 16
21
recyclerView.removeAllViewsInLayout();

The above line would help you remove all views from the layout.

For you:

@Override
protected void onRestart() {
    super.onRestart();

    recyclerView.removeAllViewsInLayout(); //removes all the views

    //then reload the data
    PostCall doPostCall = new PostCall(); //my AsyncTask... 
    doPostCall.execute();
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Saif Ahmad
  • 1,118
  • 1
  • 8
  • 24
3

This is how I cleared my recyclerview and added new items to it with animation:

mList.clear();
mAdapter.notifyDataSetChanged();

mSwipeRefreshLayout.setRefreshing(false);

//reset adapter with empty array list (it did the trick animation)
mAdapter = new MyAdapter(context, mList);
recyclerView.setAdapter(mAdapter);

mList.addAll(newList);
mAdapter.notifyDataSetChanged();
Hau Le
  • 191
  • 1
  • 4
3

Help yourself:

public void clearAdapter() {
    arrayNull.clear();
    notifyDataSetChanged();
}
Hadi Note
  • 1,386
  • 17
  • 16
2

I use this. This actually clears the recylerview completely. I had tried adapter.notifyDataSetChanged(); but it was just not updating any view in my case. Of course U had cleared the list first. But below code works fine and clears view of recyclerview completely.

  listName.clear(); // clear list
                    
  adapter = new ModelAdaptor(Activity.this, listName);
  recyclerView.setAdapter(adapter);
Ankit Mishra
  • 530
  • 8
  • 16
0

Another way to clear the recycleview items is to instanciate a new empty adapter.

mRecyclerView.setAdapter(new MyAdapter(this, new ArrayList<MyDataSet>()));

It's probably not the most optimized solution but it's working like a charm.

tryp
  • 1,120
  • 20
  • 26
0

ListView uses clear().

But, if you're just doing it for RecyclerView. First you have to clear your RecyclerView.Adapter with notifyItemRangeRemoved(0,size)

Then, only you recyclerView.removeAllViewsInLayout().

Morgan Koh
  • 2,297
  • 24
  • 24
0
private void clearRecyclerView() {
    CustomListViewValuesArr.clear();
    customRecyclerViewAdapter.notifyDataSetChanged();
}

use this func

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Ebrahim Karimi
  • 732
  • 8
  • 24
0

On Xamarin.Android, It works for me and need change layout

 var layout = recyclerView.GetLayoutManager() as GridLayoutManager;
 layout.SpanCount = GetItemPerRow(Context);
 recyclerView.SetAdapter(null);
 recyclerView.SetAdapter(adapter); //reset
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
0

For my case adding an empty list did the job.

List<Object> data = new ArrayList<>();
adapter.setData(data);
adapter.notifyDataSetChanged();
Themelis
  • 4,048
  • 2
  • 21
  • 45
0

You have better clear the array-list that you used for recyleview adapter.

arraylist.clear();
ChrisMM
  • 8,448
  • 13
  • 29
  • 48
-3
public void clearData() {
    mylist.removeAll(mylist);
    mAdapter.notifyDataSetChanged();
    recyclerView.setAdapter(mAdapter);
}
Shaun
  • 173
  • 1
  • 6
  • This doesn't help the op at all.. why are you re-setting the adapter? And you should notifyItemRangeRemoved() not your generic notifyDataSetChanged(). – Joaquim Ley Jul 22 '16 at 11:17
  • I should not re-setting the adapter,but I think mylist.removeAll(mylist) and mAdapter.notifyDataSetChanged() are right; – Shaun Jul 23 '16 at 06:46
  • actually no. The `notifyDataSetChanged()` should be your last resort, between other performance shenanigans it also breaks all the animations – Joaquim Ley Jul 23 '16 at 08:42
  • thank you,but if I delete some items, and when I do again,I can not get the item right position.what should I do ? this is my code: – Shaun Jul 25 '16 at 04:05
  • checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { item.isChecked = isChecked; if (isChecked) { item.position = position; delItems.add(item); } else { delItems.remove(item); } } }); – Shaun Jul 25 '16 at 04:16
  • ` btnDel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { for (MyPost item : delItems) { focusQuestions.list.remove(item); mHeaderAndFooterWrapper.notifyItemRemoved(item.position); } //focusQuestions.list.removeAll(delItems); //mHeaderAndFooterWrapper.notifyDataSetChanged(); delItems.clear(); btnDel.setEnabled(false); } }); ` – Shaun Jul 25 '16 at 04:17
  • Seriously, sometimes the notifyItemRangeRemoved does not work as we want. It randomly keep some viewHolders with old data. So if you want to remove all of it, the notifyDataSetChanged may be the better one to use. – Kimi Chiu Aug 21 '16 at 08:50