28

I want to use a toggle to toggle between two different views but using the same RecyclerView. Basically, once you toggle, I want the RecyclerView adapter to recall onCreateViewHolder() but this time it will use a different layout item file.

Does notifydatasetchanged() cause the adapter to rebuild itself? Or is there another way?

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
AmaJayJB
  • 1,453
  • 2
  • 14
  • 21
  • 1
    one way to find out is simply put `Log`s inside `onCreateViewHolder` and check if they are being called on `notifydatasetchanged()`... `:P` is that so hard? – SMR Feb 18 '15 at 07:21
  • 2
    Fair enough, but i actually want to know what the process is. I tried looking it up. Also that wasn't my only question. Sorry I asked – AmaJayJB Feb 18 '15 at 07:44
  • No worries if you have another question then either edit this question or delete this question and post a new question `:)`. you might wanna read [this](http://stackoverflow.com/help/how-to-ask) – SMR Feb 18 '15 at 07:46
  • 1
    No I am saying in my above post I asked what is another way of doing this. I had a feeling that the notifydatasetchanged() wouldn't do what I wanted. – AmaJayJB Feb 18 '15 at 07:51

6 Answers6

27

I needed to have two types on Views on my RecyclerView Adapter as well, one for 'regular' mode and one for multi-select mode.

So, you can override getItemViewType to force the Adapter to call your onCreateViewHolder for all views.

Add this to the Adapter code:

public void setActionMode(ActionMode actionMode) {
    this.actionMode = actionMode;
    notifyDataSetChanged();
}

@Override
public int getItemViewType(int position) {
    return (actionMode == null ? 0 : 1);
}

Add this to the ViewHolder:

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    if (viewType == 0) {
        view = inflater.inflate(R.layout.layout_1, parent, false);
    } else {
        view = inflater.inflate(R.layout.layout_2, parent, false);
    }
    ...
}

Since you return a different ViewType when in an ActionMode, the Adapter is forced to throw away all created views, and recreate everything again.

marmor
  • 27,641
  • 11
  • 107
  • 150
  • Omg this works. Just by overriding getItemViewType, even though we can technically the actionMode directly in onCreateViewHolder, forces the adapter to call onCreateViewHolder like you said. Thanks! – Bruce Jul 17 '16 at 03:09
  • i cant belive this answers save my day :D – Yudi karma Sep 04 '19 at 10:59
16

notifyDataSetChanged() calls onBindViewHolder() in case of RecyclerView

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Android Developer
  • 9,157
  • 18
  • 82
  • 139
4

THE SIMPLEST SOLUTION

If you want to refresh RecyclerView items and onCreateView() be called too, say for Grid and List LayoutManagers.

  void refreshRecyclerView(RecyclerView recyclerView){
            Adapter adapterRef=recyclerView.getAdapter();
            recyclerView.setAdapter(null);
            recyclerView.setAdapter(adapterRef);
        }

it will completely refresh the RecyclerView

//example usage
refreshRecyclerView(yourRecyclerView);
Nasib
  • 1,173
  • 1
  • 13
  • 23
  • 1
    By far the simplest solution. I have a Recycler view that adds/deletes various types of items with different view holders in different locations. Refreshing the adapter as this solution states works perfectly. Thank you. – Sneg May 30 '21 at 12:46
1

To remove and update layout in RecyclerView, you can call

mRecyclerView.removeView(view);

OR

mRecyclerView.removeViewAt(position);

after removing object in your dataset

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
streamride
  • 567
  • 4
  • 16
0

I spent more than 6 hours on this issue without any success. Finally!!! I set a global variable in the adapter and had to set it up every time i toggled the view from list to grid (in my case). the funny thing this approauch was there but I forgot to do it as static!! So my solution could be related to yours , just try it and hope it works out.

public static int mCurrentViewType;

then override the getItemType()

  @Override
    public int getItemViewType(int position) {

       return mCurrentViewType;


    }

my toggleItemViewType method:

public void toggleItemViewType () {
        if (mCurrentViewType == LIST_ITEM){
            mCurrentViewType = GRID_ITEM;
        } else {
            mCurrentViewType = LIST_ITEM;
        }
    }

I am accessing the variable from different classes, which is not right, but for now and for the sake of the onCreateViewHolder issue, it worked! if you have a better solution then good luck and share it with us. don't forget to make the global variable as "static" :)

Chosen
  • 847
  • 2
  • 9
  • 21
-1

Yes it will assume that its current data set is invalid and would need to relayout and rebind all layouts.

Kevin Crain
  • 1,905
  • 1
  • 19
  • 28