Skip to content Skip to sidebar Skip to footer

Stuttering Listview Despite Viewholder, Lazyloader And Simple Layout

I have a listview that loads images from a server into an ImageView. The Listview implements the viewholder pattern and has a very simple relative-layout for the rows. For lazy ima

Solution 1:

Stuttering can be caused by ImageView continuously requesting layout. See ImageView.setImageDrawable:

if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
    requestLayout();
}

I can see that a single list item is really complex (5 which takes a lot of time to lay out, especially if the whole list is laid out on every image load.

The key is the size of the R.drawable.placeholder. On the first load the .placeholder() is always shown, because the image must be read from the Glide disk cache (that is: background I/O). Scrolling back and forth fills the memory cache which results in immediate loads (no background thread) and also the .placeholder() is not shown for this very reason → no size change → no requestLayout().

It also helps that your ImageView has a fixed size (assuming from centerCrop()) which means that all Bitmap loaded by Glide into this view will be the same size and these Bitmaps will be recycled, so you'll probably have a 1:1 correspondence between Bitmaps in the pool and your recycled rows. Also when an existing row is recycled the ViewHolder holds an ImageView that has a same sized image already displayed in it so there will be no re-layout.

Note: Glide is not based on Volley, there's a possiblity of using Volley via volley-integration, but by default it has no dependency on it. Though this question is quite old, maybe what you stated was true before 3.0.

Solution 2:

Look at your logcat. Maybe, the stuttering you are experiencing is due to the garbage collector (GC) trying to reallocate the heap for new bitmaps (you should see GC_FOR_ALLOC logs). If that's the case, there is not much to do... ART improved the way the GC works a lot (try it on ART).

If your bitmaps are all of the same size, you can reuse the bitmaps so that the runtime doesn't have to allocate more space for new bitmaps, as stated here:

https://developer.android.com/training/displaying-bitmaps/manage-memory.html#inBitmap

If you are using Glide, you can prefill the bitmaps pool to achieve the same thing.

Solution 3:

Try changing your code to this:

if (rowView == null) {
    LayoutInflaterinflater= (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    rowView = inflater.inflate(mResource, null);
    // Create a viewHolder enabled rowNewsViewHolderviewHolder=newNewsViewHolder();
    viewHolder.newsTitle = (TextView) rowView.findViewById(R.id.news_title);
    viewHolder.newsSubTitle = (TextView) rowView.findViewById(R.id.news_sub_title);
    viewHolder.newsDescription = (TextView) rowView.findViewById(R.id.news_desc);
    viewHolder.newsDate = (TextView) rowView.findViewById(R.id.news_date);
    viewHolder.newsThumb = (ImageView) rowView.findViewById(R.id.news_thumb);
    rowView.setTag(viewHolder);
} else { // NEWNewsViewHolderholder= (NewsViewHolder) rowView.getTag();
}

Post a Comment for "Stuttering Listview Despite Viewholder, Lazyloader And Simple Layout"