58

Is there any way to redraw all items of RecyclerView?

I have some Themes (in style.xml) and after changing the theme, I need the RecyclerView to be redrawn.

So I want a method that will force to re-call onCreateViewHolder for each items of the adapter.

I tried to:

  • call adapter.notifyDataSetChanged but onCreateViewHolder is not called
  • call recyclerView.setVisibility(View.GONE) and then recyclerView.setVisibility(View.VISIBLE)
  • call recyclerView.invalidate()
  • call recyclerView.setAdapter(null) and then recyclerView.setAdapter(adapter).
    This works well for 90% items. Only 90% of items will get the new style, but some items will have the old style

I mention that the RecyclerView is attached to an Activity, not to a Fragment.

Wok
  • 4,956
  • 7
  • 42
  • 64
Denis Covaci
  • 1,137
  • 1
  • 8
  • 13

12 Answers12

51

I found the answer! The correct way to do this is:

recyclerView.setAdapter(null);
recyclerView.setLayoutManager(null);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(myLayoutManager);
myAdapter.notifyDataSetChanged();

After that, all the items are getting the new style!

Denis Covaci
  • 1,137
  • 1
  • 8
  • 13
28

Simply setting recyclerview's adapter again worked for me (I wanted RecyclerView to redraw all items' layout again)

/**
 * Forces RecyclerView adapter to call createViewHolder() - i.e. redraw all all items' layouts
 */
private fun resetAdapterState() {
    val myAdapter = recyclerView.adapter
    recyclerView.adapter = myAdapter
}
  • 1
    Or, for Java `RecyclerView.Adapter adapter = myRecyclerView.getAdapter(); myRecyclerView.setAdapter(adapter);` – DrMcCleod Nov 01 '18 at 14:35
  • 1
    Probably the best answer :) – Oleksandr Nos Nov 08 '18 at 14:01
  • I would add `recyclerView.adapter = null` before `recyclerView.adapter = myAdapter` to call `onDetachedFromRecyclerView()` on adapter automaticlly – Cililing May 08 '19 at 09:58
  • Thanks. For me, only working answer. I changed code to recyclerView.setAdapter(recyclerView.getAdapter()); Or, more simply, set Adapter again: recyclerView.setAdapter(mMyAdapter); – Cor Apr 07 '22 at 10:44
10

If you want to force redraw, you need clear View Pool of RecycleView. You can use recyclerView.getRecycledViewPool().clear();

niemmi
  • 17,113
  • 7
  • 35
  • 42
Oleg Kovalyk
  • 508
  • 5
  • 12
  • 2
    ViewHolders still not re-drawn after i call clear. Even if i call notifyDataSetChanged. Somehow still cached viewholders are re-used.. – Rik van Velzen Sep 11 '18 at 12:56
8

The below lines of code did the trick for me

recyclerview.swapAdapter(myAdapter,false);
recyclerview.setLayoutManager(myLayoutManager);
myAdapter.notifyDataSetChanged();
Edijae Crusar
  • 3,473
  • 3
  • 37
  • 74
7

I know this is old, but I had a situation where I needed to change the viewholder types after notifyDataSetChanged(). If the adapter already had data, onCreateViewHolder was not being called because of the "recycle" part of recycleviewadapter, so a type cast error was being thrown in onBindViewHolder.

I was able to solve this by calling myRecyclerView.getLayoutManager().removeAllViews(); before calling notifyDataSetChanged(); on the adapter.

D Myers
  • 91
  • 1
  • 5
7

Resetting the Adapter worked for me, I called this inside onConfigChange

myRecyclerView.setAdapter(myAdapter)
Aziz
  • 1,976
  • 20
  • 23
  • This answer worked for me when I needed to remove selections after exiting a multi-selection mode. I notified the related fragment through an interface method, inside of which I reset the adapter as this answer suggests. – Cherif Diallo Jun 26 '20 at 15:01
4

The only solution that worked for me on an Amazon Fire HD was this:

recyclerView.setAdapter(null);
recyclerView.setLayoutManager(null);
recyclerView.getRecycledViewPool().clear();
recyclerView.swapAdapter(myAdapter, false);
recyclerView.setLayoutManager(layoutManager);
myAdapter.notifyDataSetChanged();

Hope it helps!

2

Take a look at this answer: https://stackoverflow.com/a/33342314/4142087

Shortly, you can create different types of view holders, changing view type will force RecyclerView to pass another ViewHolder to the onBindViewHolder.

If you use setTheme, you have to recreate whole Activity like this: https://stackoverflow.com/a/14367214/4142087

Community
  • 1
  • 1
Anton Shkurenko
  • 4,301
  • 5
  • 29
  • 64
1

This works for me:

recyclerView.adapter = recyclerView.adapter
recyclerView.post {
    recyclerView.adapter?.notifyDataSetChanged()
}

It shows blank if running without post{}

Tuan Chau
  • 1,243
  • 1
  • 16
  • 30
  • 1
    Doing recyclerView.adapter = recyclerView.adapter without notifyDataSetChanged() worked for me. – draziw May 23 '22 at 13:19
1

Redraw the Recycler again Kotlin:

viewLifecycleOwner.lifecycleScope.launch {
                   delay(3000L)
                   binding.recyclerView.adapter.also {
                       binding.recyclerView.adapter = null
                       binding.recyclerView.adapter = it
                   }
moken
  • 3,227
  • 8
  • 13
  • 23
ASDzendo
  • 31
  • 1
  • Please read "[answer]" and "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code. – the Tin Man Apr 21 '23 at 21:57
0

Force RecyclerView to onCreateViewHolder or redraw its items #Kotlin

This worked for me

        this.runOnUiThread {
            val adapter = recyclerView.adapter
            val layoutManager = recyclerView.layoutManager
            recyclerView.adapter = null
            recyclerView.layoutManager = null
            recyclerView.adapter = adapter
            recyclerView.layoutManager = layoutManager
            adapter!!.notifyDataSetChanged()
        }

hope this can help

Chea Sambath
  • 1,305
  • 2
  • 13
  • 16
  • You should add that this case works for code execution (callback method) from background. Reason your code would not work is for callback being executed in different thread then main. – David Vareka Mar 15 '21 at 12:48
0

After trying most of the ideas here - if turns out that my issue was down to using a simulator. When testing on devices I've had no issues with this.

O Wigley
  • 157
  • 1
  • 4