RecyclerView
Android Development
notifyDatasetChanged
UI Issue
Debugging

RecyclerView blinking after notifyDatasetChanged

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

RecyclerView blinking after notifyDataSetChanged() usually means the whole list is being rebound and reanimated even though only a few items actually changed. The UI appears to flash because RecyclerView loses the opportunity to perform fine-grained updates.

The real fix is almost never "turn off RecyclerView." It is to stop invalidating the entire dataset and instead give RecyclerView enough information to update only the changed rows.

Why notifyDataSetChanged() Causes Flicker

notifyDataSetChanged() tells the adapter that everything may have changed. RecyclerView then has to assume:

  • positions may be different
  • contents may be different
  • item animations may need to run broadly

That is expensive and visually noisy. Even if only one checkbox changed, the whole visible list may be rebound.

Prefer Fine-Grained Notifications

If you know exactly what changed, call the specific method:

  • 'notifyItemChanged(position)'
  • 'notifyItemInserted(position)'
  • 'notifyItemRemoved(position)'
  • 'notifyItemMoved(from, to)'

Example:

kotlin
1fun updateItem(position: Int, newValue: String) {
2    items[position] = newValue
3    notifyItemChanged(position)
4}

This lets RecyclerView preserve more UI state and animate only what actually changed.

Better Yet: Use ListAdapter and DiffUtil

For most modern Android code, DiffUtil is the right tool because it calculates the minimal set of changes between the old list and the new one.

kotlin
1class NoteAdapter : ListAdapter<Note, NoteViewHolder>(DIFF) {
2    companion object {
3        val DIFF = object : DiffUtil.ItemCallback<Note>() {
4            override fun areItemsTheSame(oldItem: Note, newItem: Note): Boolean {
5                return oldItem.id == newItem.id
6            }
7
8            override fun areContentsTheSame(oldItem: Note, newItem: Note): Boolean {
9                return oldItem == newItem
10            }
11        }
12    }
13}

Then submit a new list:

kotlin
adapter.submitList(updatedNotes)

This approach avoids manual bookkeeping and usually removes the blinking problem entirely.

Stable IDs Can Help

If items have real persistent identities, enable stable IDs so RecyclerView can match old and new rows more reliably:

kotlin
override fun getItemId(position: Int): Long = items[position].id

And in the adapter init path:

kotlin
setHasStableIds(true)

This is especially useful when the list changes often but items themselves keep the same identity.

Disable Change Animations Only If Needed

Sometimes the content update is correct, but the default item animator makes it look like a blink. In that case, disabling change animations can help:

kotlin
(recyclerView.itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations = false

This is a tactical fix, not the first fix. If you are still using notifyDataSetChanged() everywhere, turning off animations only hides the underlying problem.

Preserve Identity Across Updates

Blinking also gets worse when RecyclerView cannot tell which old row corresponds to which new row. That is why stable IDs and correct DiffUtil identity checks matter so much. If item identity changes unnecessarily between submissions, RecyclerView behaves as though rows disappeared and reappeared instead of merely updating in place.

If your rows contain images or expensive binds, this identity problem becomes even more visible because each unnecessary rebind can restart image loading, placeholder transitions, or view-state restoration.

That is one reason list updates that are technically correct can still feel visually broken.

Common Pitfalls

  • Calling notifyDataSetChanged() for every tiny update.
  • Recreating the adapter instead of updating the existing list.
  • Using DiffUtil but implementing areItemsTheSame incorrectly.
  • Forgetting stable IDs when items have long-lived identities.
  • Disabling animations before fixing the update logic.

Summary

  • RecyclerView blinking usually comes from broad invalidation and rebinding.
  • Avoid notifyDataSetChanged() when you know what changed.
  • Prefer DiffUtil or ListAdapter for list updates.
  • Stable IDs improve item matching across updates.
  • Disable change animations only as a final polish step, not as the primary fix.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.