2

I'm looking for a great way to speed up the Gallery view widget in Android Honeycomb. I'm currently using it to display some fairly large images at roughly 340 x 600 pixels, and I'd love for it to be smooth as butter when scrolling through the images.

It's fairly speedy at the moment, but it doesn't compare to loading a ScrollView with ImageViews and scrolling through that.

Here's a simplified version of my getView() method from my custom BaseAdapter:

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

        if (convertView == null) {
            convertView = (ImageView) new ImageView(Main.this);
        }

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPurgeable = true;

        ((ImageView) convertView).setImageBitmap(createReflection(BitmapFactory.decodeFile(ImageFile, options)));

        convertView.setPadding(20, 0, 20, 0);

        return convertView;
    }

I've been experimenting with lazy loading the images, but I didn't really like the result.

Michell Bak
  • 13,182
  • 11
  • 64
  • 121
  • What did Traceview show when you ran it to measure where your performance issues lie? – CommonsWare Aug 06 '11 at 22:59
  • I would love to tell you, but I can't get Traceview to work in Eclipse :( – Michell Bak Aug 06 '11 at 23:07
  • I got it working now. Traceview says 52 ms each time getView() is called, and somewhere between 46 and 48 ms of it is being used decoding the images. Mind you, this is running on an overclocked tablet @ 1.2 GHz instead of the standard 1.0 GHz, so I'm expecting it to be a tad slower on the default clock speed. – Michell Bak Aug 06 '11 at 23:17

4 Answers4

2

The difference between using a Gallery and:

loading a ScrollView with ImageViews and scrolling through that

is that with the ScrollView scenario, you are pre-loading all of the images, rather than loading them on the fly as you are in the Gallery scenario.

If your number of images is small, and you have enough RAM to support all of them, then just use your ScrollView.

Beyond that, AFAIK there's not a ton you can do. You can maintain a bitmap cache where you continue decoding a few images ahead of the current ones in the Gallery and have your Adapter pull from the cache. However, that will only get you so far -- small scrolls will be smooth, but flings past your cache capacity will still result in the decoding being done on demand. That's pretty much unavoidable.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Yeah, I was kind of expecting that answer. The thing is that I cannot be sure how many ImageViews are displayed - it could be anywhere between a few and thousands, so I simply cannot pre-load them all. That's what I did in the initial versions of my application, but it caused OOM errors with some people because they had more images displayed (I'm working on a movie management application, where each image is the cover art for the movie - check out Mizuu Movies on Market for a visual explanation). I've been thinking that I could perhaps load smaller images during scroll, but I really don't know – Michell Bak Aug 06 '11 at 23:28
  • You could try creating parallel low resolution renditions of the images and try to decode those ahead of time, using them as placeholders for a lazy-load rather than some static placeholder. Android can stretch the low-resolution images -- this is more or less the effect you get when you zoom into Google Map tiles. You might even try a blur effect so that the scaled-up low-res images don't look so pixelated. If you can keep your low-resolution file size to ~1K, you might be able to load thousands of those. Note that I'm just brainstorming here, having never tried this technique... :-) – CommonsWare Aug 06 '11 at 23:38
  • Thanks a lot, CW. I'll probably give lazy loading another go - cheers! :) – Michell Bak Aug 06 '11 at 23:48
2

Gallery does not support the convertView at the moment. You will always receive null for convertView. This is a known issue and there's no ETA for a fix.

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
0

Turning on Hardware acceleration of your application will have a significant impact (at least had it on my example app).

Add android:hardwareAccelerated="true" in the application element of your android manifest http://developer.android.com/guide/topics/manifest/application-element.html#hwaccel

dparnas
  • 4,090
  • 4
  • 33
  • 52
  • Hardware acceleration was enabled, but yeah, that does speed up things quite a bit, especially when dealing with large Bitmaps. – Michell Bak Oct 31 '11 at 10:43
0

One of the elements which is slowing your Gallery view down is file IO. I'm working on a slideshow app for which I have photos in 1280x720 resolution. The actual file I/O takes 300-400 ms for each file.

Since the File I/O would normally run on the UI thread, this will cause a very visible "hick" in any ongoing photo transition.

In order to avoid this, you should:

  1. Set a temporary loading drawable that is already cached imageView.setImageResource(R.drawable.my_loading_drawable);
  2. Create an AsyncTask which
    • loads the drawable in doInBackground(i.e. the File I/O)
    • Updates the imageView in onPostExecute imageView.setImageDrawable(drawable);

PS if the user flicks through multiple pictures, the above approach will typically trigger multiple parallell asynctask which all will be using file I/O. Not good for performance and may crash your app. You should probably have more structured approach where you only allow one async task at a time.

dparnas
  • 4,090
  • 4
  • 33
  • 52