Recyclerview Slow Scrolling Performance and Lag/Halt Sometime While Scrolling

RecyclerView scrolling laggy on newer android versions

I solved the problem by setting the build variant to release after finding this comment: Performance of ConstraintLayout inside RecyclerView ViewHolder.

The example shared here is smoothly then and my application with Glide performs more smoothly, too, even without setting layout_width to ConstraintLayout.

But it's unclear to me why this lag appears in the debug mode and only on the latest android versions.

Android RecyclerView Scrolling Performance

I've recently faced the same issue, so this is what I've done with the latest RecyclerView support library:

  1. Replace a complex layout (nested views, RelativeLayout) with the new optimized ConstraintLayout. Activate it in Android Studio: Go to SDK Manager -> SDK Tools tab -> Support Repository -> check ConstraintLayout for Android & Solver for ConstraintLayout. Add to the dependencies:

    compile 'com.android.support.constraint:constraint-layout:1.0.2'
  2. If possible, make all elements of the RecyclerView with the same height. And add:

    recyclerView.setHasFixedSize(true);
  3. Use the default RecyclerView drawing cache methods and tweak them according to your case. You don't need third party library to do so:

    recyclerView.setItemViewCacheSize(20);
    recyclerView.setDrawingCacheEnabled(true);
    recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
  4. If you use many images, make sure their size and compression are optimal. Scaling images may also affect the performance. There are two sides of the problem - the source image used and the decoded Bitmap. The following example gives you a hint how to decode аn image, downloaded from the web:

    InputStream is = (InputStream) url.getContent();
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    Bitmap image = BitmapFactory.decodeStream(is, null, options);

The most important part is specifying inPreferredConfig - it defines how many bytes will be used for each pixel of the image. Keep in mind that this is a preferred option. If the source image has more colors, it will still be decoded with a different config.


  1. Make sure onBindViewHolder() is as cheap as possible. You can set OnClickListener once in onCreateViewHolder() and call through an interface a listener outside of the Adapter, passing the clicked item. This way you don't create extra objects all the time. Also check flags and states, before making any changes to the view here.

    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    Item item = getItem(getAdapterPosition());
    outsideClickListener.onItemClicked(item);
    }
    });
  2. When data gets changed, try to update only the affected items. For example instead of invalidating the whole data set with notifyDataSetChanged(), when adding / loading more items, just use:

    adapter.notifyItemRangeInserted(rangeStart, rangeEnd);
    adapter.notifyItemRemoved(position);
    adapter.notifyItemChanged(position);
    adapter.notifyItemInserted(position);
  3. From Android Developer Web Site :

Rely on notifyDataSetChanged() as a last resort.

But if you need to use it, maintain your items with unique ids:

    adapter.setHasStableIds(true);

RecyclerView will attempt to synthesize visible structural change
events for adapters that report that they have stable IDs when this
method is used. This can help for the purposes of animation and visual
object persistence but individual item views will still need to be
rebound and relaid out.

Even if you do everything right, chances are that the RecyclerView is still not performing as smoothly as you would like.

Recyclerview beings to lag after multiple activity instances

No, this is not the expected behavior, and yes, definitely sounds like a memory leak. Unfortunately, there is no way for us to really help you with finding the memory leak without seeing more of your code. I would check if there is any reference of the previous activity inside the new activity, or any static references, or anything that would cause the previous activity to not get cleaned up.

Do you need to open the same activity but with a new instance of it? Do you want to keep the back stack behavior? If not, you should reuse the same activity but pass it a new Intent to rebind the new data and make the activity singleTop or singleTask.

UI lags and is choppy when using Glide to load images in a RecyclerView

I finally figured out the issue after a lot of trial and error. My first mistake was not posting my xml layout file for the recyclerview item because that was the source of the performance issues. The second mistake was that I was using a LinearLayout and had set its own layout_width and layout_height attributes to 75dp instead of the ImageView's which is nested inside of the LinearLayout and was using wrap_content for the ImageView's respective attributes. So to fix the performance issues i did the following :

  1. I changed the LinearLayout to a ConstraintLayout (i read that it is much more optimized in general)
  2. I set the ConstraintLayout's layout_width & layout_height attributes to wrap_content and finally
  3. I set the actual ImageView's layout_width & layout_height attributes to 75dp which is the actual size that i want the image to be

Here's the final layout file for each item of the recyclerview after the changes :

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:padding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<ImageView
android:id="@+id/cardIcon"
android:layout_width="75dp"
android:layout_height="75dp"
android:contentDescription="cardIcon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars" />
</androidx.constraintlayout.widget.ConstraintLayout>

RecyclerView inside RecyclerView not smoothly

There is no issue in such an approach as long as they scroll along different axes.You could enable RecyclerView.startNestedScroll(int) and also handle situations like overscroll.This delay would be because you are reinitiating an adpater everytime. You could try something different like maintaining a map of adpaters and calling RecyclerView.swapAdapter(args...) in bindVH.

Another good step could also be using a common pool for recycled views using RecyclerView.setRecycledViewPool(args...) .
I have created and used a list of 100+ plus items with a nested (different axis) recycler and have not faced issues .

If you would provide more code( where you have written async loading) I could help you more.But I suggest you go through the API and the design patterns and that should solve your issue.



Related Topics



Leave a reply



Submit