Force RecyclerView to redraw its items
Asked Answered
D

12

59

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.

Dutch answered 8/4, 2016 at 8:30 Comment(3)
Make sure you call notifyDataSetChanged() from the UI thread, it should work.Chemosynthesis
@Chemosynthesis notifyDataSetChanged only force onBindNewHolder, not onCreateBourgeois
Sorry, im not familiarized with the viewHolder pattern but i will say that you should adapt your code to work with it (or dont use it).Chemosynthesis
D
52

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!

Dutch answered 8/4, 2016 at 9:26 Comment(4)
adapter.doYourStaff();recyclerView.setAdapter(adapter); This 2 lines of code is enough!Thailand
recyclerView.setAdapter(adapter) is enough for me.Mission
This worked for me too except I didn't need the first two lines (i.e. null assignments).Cullie
I checked recyclerView and myAdapter for not being null before applying and works fineFabrizio
S
30

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
}
Selfcontrol answered 19/6, 2018 at 16:51 Comment(4)
Or, for Java RecyclerView.Adapter adapter = myRecyclerView.getAdapter(); myRecyclerView.setAdapter(adapter);Dejected
Probably the best answer :)Merilyn
I would add recyclerView.adapter = null before recyclerView.adapter = myAdapter to call onDetachedFromRecyclerView() on adapter automaticllyInteractive
Thanks. For me, only working answer. I changed code to recyclerView.setAdapter(recyclerView.getAdapter()); Or, more simply, set Adapter again: recyclerView.setAdapter(mMyAdapter);Patman
G
12

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

Generous answered 22/12, 2016 at 10:51 Comment(1)
ViewHolders still not re-drawn after i call clear. Even if i call notifyDataSetChanged. Somehow still cached viewholders are re-used..Elute
J
8

The below lines of code did the trick for me

recyclerview.swapAdapter(myAdapter,false);
recyclerview.setLayoutManager(myLayoutManager);
myAdapter.notifyDataSetChanged();
Jaynes answered 16/2, 2017 at 20:56 Comment(0)
P
8

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

myRecyclerView.setAdapter(myAdapter)
Photocathode answered 9/5, 2020 at 12:19 Comment(1)
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.Botany
H
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.

Homologize answered 22/11, 2019 at 17:48 Comment(0)
T
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!

Taxis answered 6/6, 2018 at 9:30 Comment(0)
B
2

Take a look at this answer: https://mcmap.net/q/331006/-force-recyclerview-to-call-oncreateviewholder

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://mcmap.net/q/143666/-how-to-change-current-theme-at-runtime-in-android-duplicate

Bourgeois answered 8/4, 2016 at 8:53 Comment(2)
If thats how this shoud be done that viewholder pattern doesnt look as the cleanest.Chemosynthesis
@DenisCovaci Try to save data in the instance state and recreate activityBourgeois
S
1

This works for me:

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

It shows blank if running without post{}

Serigraph answered 14/9, 2021 at 11:41 Comment(1)
Doing recyclerView.adapter = recyclerView.adapter without notifyDataSetChanged() worked for me.Sophisticated
J
1

Redraw the Recycler again Kotlin:

viewLifecycleOwner.lifecycleScope.launch {
                   delay(3000L)
                   binding.recyclerView.adapter.also {
                       binding.recyclerView.adapter = null
                       binding.recyclerView.adapter = it
                   }
Januarius answered 17/4, 2023 at 18:32 Comment(1)
Please read "How to Answer" and "Explaining entirely code-based answers". 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.Ladybird
H
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

Hanaper answered 17/5, 2020 at 8:14 Comment(1)
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.Redmon
C
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.

Comptroller answered 5/6, 2021 at 18:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.