0

For last 10+ hours I try to get a large (40+) amount of images (in ImageButton format) on a single Android screen without out of memory errors. The activity I work on is an image picker for a coloring book app. Images are of various sizes in the range of (500 to 1200)x(500 to 1200), PNGs (if that matters).

I have tried:

  • Horizontal Scroll View with images added from the code. The result is slow (I do it on UI thread) and consumes large memory space.
  • Horizontal Scroll View with images added from the code via AsyncThread. The result is fast but still consumes large memory space. I like the user experience of this one the most!
  • Grid View and List View - both are very choppy (testing on first Nexus 7). Memory usage is better.

What I am considering

  • View Pager - first results look better than Grid View from performance perspective (I have not completed it to the moment to assess the memory usage but it should be better from what I understand). Yet, I dislike the user experience and prefer a scrollable list of all images.
  • Conversion of my resources to JPG (will that get rid of Transparency byte?)
  • Downsizing the images to max 500x500px

None of the solutions seems as good as the Android Photo Gallery app available on all devices. This experience is what I would love to mirror. No idea how this is done though :(

Two questions.

  1. What is the best way to get such thing (40+ Images scrollable on single screen) done? Is it really ViewPager? ScrollView with AsyncTask and well thought images resolution? Something I have not tried yet?
  2. What is the memory limit I should try to keep below? Looking at Android heap size on different phones/devices and OS versions it seems to be 256 MB, is that fair assumption?

Thanks. Have a great weekend!

PS. On iOS all works like charm when I add all the buttons into a scroll view :(

Community
  • 1
  • 1
Piotr
  • 1,597
  • 3
  • 18
  • 25
  • Consider using an external library such as `Universal Image Loader`, or `Picasso` (http://square.github.io/picasso/) if you are loading them from the internet. – EpicPandaForce Mar 20 '15 at 20:51
  • 40 images at the same time or not? It does matter. It would be great if you show screen of your app. – eleven Mar 20 '15 at 20:51
  • 3
    Why are you trying to load a 500x500 image onto a button? Create a thumbnail at a more reasonable size (perhaps 50x50) and use that. Load the full size image when it's selected. –  Mar 20 '15 at 20:51
  • Check the android source code for the gallery app. And @Hobo Sapiens is correct, there's really no reason to load full images until one is selected – jb15613 Mar 20 '15 at 21:01
  • You seem to have some contradictions in your question. You mention `ViewPager` but say "Yet, I dislike the user experience and prefer a scrollable list of all images.". Then you mention "...the Android Photo Gallery app..." and say "This experience is what I would love to mirror.". Previously you mention using a Nexus 7...well I have a Nexus 7 and the Photos app which came pre-installed uses a `ViewPager` when viewing images as full screen. How come you love the built-in Photos app but dislike the UX of `ViewPager`? – Squonk Mar 20 '15 at 21:24
  • Thanks for all the comments. I highly appreciate your input! ViewPager vs Gallery App - I like the presentation of multiple photos. They seem to load in the background so I will probably keep the AsyncTask based loader. – Piotr Mar 21 '15 at 08:51

1 Answers1

3

Some basic calculations reveals your problem:

40+ images at 1200x1200 = approx 57MB, the comments are correct you need to subsample (i.e. thumbnail) the images or use a library such as the Universal Image Loader. Converting to JPG doesn't matter. That is a compressed storage format, the memory required to display the pixels remains the same.

There is a Android Developers article on Loading Large Bitmaps Efficiently with sample code. The following steps are covered in more detail in the article Android Bitmap Loading for Efficient Memory Usage.

The basic steps in loading a large bitmap are:

  • Determine the required size (from a known size or determining the size of the target View).
  • Use the BitmapFactory class to get the bitmap’s size (set inJustDecodeBounds in BitmapFactory.Options to true).
  • Calculate the subsampling value and pass it to the BitmapFactory.Options setting inSampleSize.
  • Use the BitmapFactory to load a reduced size bitmap.
Daniel S. Fowler
  • 1,982
  • 15
  • 12
  • Thanks I believe that will be the way to proceed. Do you know if it makes any difference to use JPGs vs PNGs (transparency byte?) or use ARGB4444 / RGB565 vs ARGB8888 when creating a Bitmap? – Piotr Mar 21 '15 at 08:52