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

glide loading images each time when scrolling recyclerview
glide recyclerview slow
recyclerview lags on scroll
glide load images faster
recyclerview slow to load
recyclerview load all items
glide recyclerview integration
android image gallery using glide in recyclerview

I have a RecyclerView that loads images from URLs using Glide. Now the URLs are retrieved from Firebase using pagination as you can see below. The issue is that when the MainActivity (which contains the below code and the recyclerview) is first initialized there is a substantial lag in the UI (very laggy and choppy scrolling, options menu takes 3 seconds to open etc.) and the images take a while to load. After i scroll down though and reach the end of the RecyclerView for the first page of data, the OnScrollListener is triggered and i start loading new data from a new query. I've tried my best to optimize what Glide does based on suggestions from a user on another post i made and i also set the adapter.setHasFixedSize to true without luck. Any idea what's happening here? Am i hanging the UI thread somehow despite the queries being async?

EDIT : Could Glide be causing the lag on the main Thread due to it having to load multiple images into the recycler view's imageViews? And if so, what can i do to counter that?

Here's how i handle the pagination of the data i get from Firebase and notify the adapter:

class MainActivity : AppCompatActivity() {

private val TAG: String = MainActivity::class.java.simpleName // Tag used for debugging
private var queryLimit : Long = 50 // how many documents should the query request from firebase
private lateinit var iconsRCV : RecyclerView // card icons recycler view
private lateinit var lastVisible:DocumentSnapshot

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val rootRef: FirebaseFirestore = FirebaseFirestore.getInstance()
    val urlsRef : CollectionReference = rootRef.collection("CardIconUrls")
    val query : Query = urlsRef.orderBy("resID",Query.Direction.ASCENDING).limit(queryLimit) // create a query for the first queryLimit documents in the urlsRef collection

    // Setting Toolbar default settings
    val toolbar : Toolbar = findViewById(R.id.mainToolbar)
    setSupportActionBar(toolbar) // set the custom toolbar as the support action bar
    supportActionBar?.setDisplayShowTitleEnabled(false) // remove the default action bar title

    // RecyclerView initializations
    iconsRCV = findViewById(R.id.cardIconsRCV)
    iconsRCV.layoutManager = GridLayoutManager(this,5) // set the layout manager for the rcv
    val iconUrls : ArrayList<String> = ArrayList() // initialize the data with an empty array list
    val adapter = CardIconAdapter(this,iconUrls) // initialize the adapter for the recyclerview
    iconsRCV.adapter = adapter // set the adapter
    iconsRCV.setHasFixedSize(true)

    iconsRCV.addOnScrollListener(object:OnScrollListener(){
        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)

            if(!iconsRCV.canScrollVertically(1) && (newState == RecyclerView.SCROLL_STATE_IDLE) && ((iconsRCV.layoutManager as GridLayoutManager).findLastVisibleItemPosition() == (iconsRCV.layoutManager as GridLayoutManager).itemCount-1)) {
                Log.d(TAG,"End of rcv-Starting query")
                val nextQuery = urlsRef.orderBy("resID",Query.Direction.ASCENDING).startAfter(lastVisible).limit(queryLimit).get().addOnCompleteListener { task ->
                    if(task.isSuccessful) {
                        Log.d(TAG,"Next query called")
                        for(document:DocumentSnapshot in task.result!!) {
                            iconUrls.add(document.get("url").toString())
                        }
                        lastVisible = task.result!!.documents[task.result!!.size()-1]
                        adapter.notifyDataSetChanged()
                    }
                }
            }
        }
    })

    query.get().addOnCompleteListener {task: Task<QuerySnapshot> ->
        if(task.isSuccessful) {
            Log.d(TAG,"Success")
            for(document:DocumentSnapshot in task.result!!) {
                Log.d(TAG,"Task size = " + task.result!!.size())
                iconUrls.add(document.get("url").toString()) // add the url to the list
            }
            lastVisible = task.result!!.documents[task.result!!.size()-1]
            adapter.notifyDataSetChanged() // notify the adapter about the new data
        }
    }
}

Here's the recyclerview adapter:

public class CardIconAdapter extends RecyclerView.Adapter<CardIconAdapter.ViewHolder> {

    private List<String> urlsList;
    private Context context;

    class ViewHolder extends RecyclerView.ViewHolder {
        ImageView iconImg;
        ViewHolder(@NonNull View view) {
            super(view);
            iconImg = view.findViewById(R.id.cardIcon);
        }
    }

    public CardIconAdapter(Context cntxt, List<String> data) {
        context = cntxt;
        urlsList = data;
    }

    @NonNull
    @Override
    public CardIconAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view =  LayoutInflater.from(parent.getContext()).inflate(R.layout.card_icons_rcv_item,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull CardIconAdapter.ViewHolder holder, int position) {
        RequestOptions requestOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL);
        GlideApp.with(context).load(urlsList.get(position)).thumbnail(0.25f).centerCrop().dontTransform().apply(requestOptions).into(holder.iconImg);
    }

    @Override
    public int getItemCount() {
        return urlsList.size();
    }
}

Recyclerview scrolling causes glide to lag when using wrap_content , When using wrap_content in the imageview, Glide's caching does not do: here's a view that will grow as large as it needs to be, load an image into it. Change the list image height to become fixed because of this lag issue: When using wrap_content in the imageview, Glide's caching does not seem to work which causes a large amount of lag in the interface. I am able to fix the issue by using a fixed size either through the xml or with the ".override" method f

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>

Heavy lag in recyclerview when scrolling cached images � Issue , 4.7.1: Galaxy Note 8 / Android 8.0: Issue details / Repro steps / Use case background: RecylcleView Heavy lag in recyclerview when scrolling cached images #3050 Drawable=com.bumptech.glide.load.resource.bitmap. Based on the above two and the async nature of Glide it shouldn't be lagging. Excessive re-layout can cause lags, try to disable Glide to see if it happens without. Can you please describe your problem in a little more detail? Also add adapter (mostly onBindVH), Glide load line and layout XML for list items.

Try to use paging library combined with recyclerview

link reference:

Paging Library for Android With Kotlin: Creating Infinite Lists

Android Jetpack: manage infinite lists with RecyclerView and Paging (Google I/O '18)

UI lags and is choppy when using Glide to load images in , 问题. I have a RecyclerView that loads images from URLs using Glide. Now the URLs are retrieved from Firebase using pagination as you can see below. Implementing RequestManager in RecyclerView Adapter constructor with context from fragment ie GlideApp.with(this) Implementing 'com.github.bumptech.glide:recyclerview-integration:4.7.1' to preload. Stripping the layout to just the imageview.

What are some of your tricks to speed up your recyclerview?, News for Android developers with the who, what, where when and how of the Android listener to your RecyclerView, and then if you are using Glide/Picasso, dont' forget to If you're manually loading images here, then maybe just call ImageView. Our design documents for new features and UI usually based on iOS� I use Glide library to load image in the RecyclerView and happen to meet this “ghost image” problem like following. I’m using Glide of version 3.7.0 . You just scroll down and scroll up back and forth fast.

RecyclerView scroll lag ONLY at fist scroll : androiddev, I'm loading some data and images in the background, then I set the adapter to the recyclerview. Once I scroll a little bit, the phone starts to lag, but after that I can scroll the other 80% without any lag. I've tried using Glide 4, but not 3. But this job offer: https://www.jetbrains.com/careers/jobs/ui-framework-developer-401 /� Glide 3.x. Glide .with(context) .load(UsageExampleListViewAdapter.eatFoodyImages[0]) .override(600, 200) // resizes the image to these dimensions (in pixel). resize does not respect aspect ratio .into(imageViewResize); This option might also be helpful when you load images when there is no target view with known dimension yet.

Android-Recycler lags when scrolling with Glide (Android forum at , Mobile � Android. Android-Recycler lags when scrolling with Glide When scrolling down, recycler starts to lag while glide loads asynchronous images. public void onBindViewHolder( final RecyclerView. .load(customer. Glide Version: 3.7.0 Integration libraries: okhttp3-integration:1.4.0 Device/Android Version: Nexus 6 7.1.1 Issue details / Repro steps / Use case background: Using Glide with a RecylerView; the image in question starts off screen at the

Comments
  • Self dupe of Glide loads images from firebase painfully slow using URLs.
  • @MartinZeitler why is it a duplicate? In the post you linked, i was having trouble loading images faster through Glide in a RecyclerView and that was solved (user still hasn't added the answer though) and in this one i'm having performance issues with my Recycler view (lag, UI lag, removal of previous data etc.).
  • To me this seems quite alike the same problem; try caching these thumbnails instead of down-scaling them on the fly (which might be a waste of battery, because it needs CPU). Already serving them at the intended size would eliminate the need to manipulate them, altogether (and Glide is not required to do so). I mean, down-scaling one image is no problem - but down-scaling a whole bunch of images is.
  • @MartinZeitler doesn't Glide automatically cache them? Even when i wasn't down-sampling them on the fly i was still getting long loading issues but now the recycler view is also lagging and the previous data are loading weirdly (if they load at all)
  • your recycler view implimentation is different little bit. kindly post your node structure of firebase db how data is going to store.
  • Sadly i don't see any difference, i mean they are loading non-stop without progress after like 2 minutes and still going. This is what the ui looks like : imgur.com/a/Ie45UCi . I also noticed that in the logcat i get no actual errors so i find it really hard to get to the root of this issue.
  • overriding height and width of image can improve recyclerview performance if u need to show progress when loading refer this stackoverflow.com/a/55632581/10239870
  • I'm actually paging the data as you can see in my code. I load pages of data where each page consists of 50 icons and new ones are only requested after scrolling to the bottom of the recycler view. I just haven't used the Paging library because i don't think it would be worth to go through all the docs etc. for such simple data (strings). Have you tried it for something similar and saw significant performance improvements?