Android - GC lags listview scrolling with "bigger" images

In a listview I want to draw one image on a list entry. These 20 images have to scale to fill the width in vertical mode. The phone resolution is 480 x 800 pixels (SGS2). The images resolution is 400x400 and are about 100KB in size. I've placed the images in the drawable folder.

When I scroll through the list it's not going smooth.

I understand a few things: - application Heap size = limited, Allocated when first run = 13MB, got 1 MB left. - I have GC_FOR_ALLOC Log messages, which halts the system for 15ms. (this is my lagg in scrolling, I think). - After changing the code I also see GC_CONCURRENT messages.

With these GC messages, I understand my garbage-collection kicks in every time I scroll to another image in a new listview entry. This I can analyse so far, but I don't know exactly what to do to fix and remove the GC permanently. I have scaled down the images to 100x100 and it postpones the GC messages for a longer time. But eventually the GC kicks in. I do recycle the views with convertview, and use holders inside the views already.

I've read about re-using image memory, but not sure if and how I do this. Or, maby it's "normal" when using these larger images in a listview and I need to rethink the drawing of the images and only start drawing when the scolling ends?

Should I be using Listview for scrolling through pictures?

2012-12-31_02:11 I've implemented the setOnScrollListener, which makes scrolling smooth. I think this is the piece of code I have to investigate further to butter things up.


listview adapter
public class ListviewAdapter extends BaseAdapter {

    private static Activity activity;
    private int[] data;
    private static LayoutInflater mInflater = null;

    public ListviewAdapter(Activity a, int[] d) {
        activity = a;
        data = d;
        mInflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public int getCount() {
        return data.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.listviewitem, parent,
                    false);
            holder = new ViewHolder();

            holder.picture = (ImageView) convertView.findViewById(R.id.image);
            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        if (!MainActivity.isScrolling) {
    holder.picture.setImageResource(data[position]);
    }

        return convertView;
    }

    static class ViewHolder {
        ImageView picture;
    }

}

listview XML
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <ImageView
      android:id="@+id/image"
      android:src="@drawable/stub"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:contentDescription="Animal images"
        android:scaleType="fitCenter"
        android:scrollingCache="false"
        android:animationCache="false" 
        />

</LinearLayout>

Answers


There are lots of techniques to make ListViews faster. See Efficient ListView in android. You should recycle Views, which will decrease Garbage Collection. You might also consider not loading Images before the list scrolling has stopped, see Lazy Load images on Listview in android(Beginner Level)?.


You are opening Bitmaps all the time, those take a considerable amount of memory that needs to be collected so that there is space for the awful lot of Bitmaps that you will be loading next.

You could start by using the BitmapFactory Options to subsample the load image if its not going to be displayed at full size. That way, you only take as much memory as needed to fill your view, causing less GC calls.

You could also try keeping some kind of cache inside your adapter, to avoid reloading Bitmaps every time.


Need Your Help

On your very first program, which construct hooked you on programming?

language-agnostic language-construct

To me it was the If statement, I'm psyched up, since then I believed that computers are very intelligent, or I can at least make it appear intelligent because of it.