2

whats up folks.

I'm trying to make a product catalog and this is what i'm doing:

  • Activity with ViewPager -- Each Product is a Fragment in this ViewPager. -- Each Fragment have a Gallery.

I download the products data and images from web and store the images into the sdcard.

But my app keep crashing and this is the error

05-22 10:04:43.829: E/AndroidRuntime(12388): FATAL EXCEPTION: main
05-22 10:04:43.829: E/AndroidRuntime(12388): java.lang.OutOfMemoryError
05-22 10:04:43.829: E/AndroidRuntime(12388):    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
05-22 10:04:43.829: E/AndroidRuntime(12388):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
05-22 10:04:43.829: E/AndroidRuntime(12388):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
05-22 10:04:43.829: E/AndroidRuntime(12388):    at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:324)

I was using de bitmap factory inside the getView on Adapter of the Gallery, but it crashes when i swipe the Fragments. Then I changed and create and List when the Main Activity was created, but now if I close the activity and try to open it again, it crashes, THEN if i try to open again it opens normally.

What i`m doing wrong? There is a better way to do that?

this is my adapter to Gallery

public class ImagemAdapter extends BaseAdapter {

        private Context ctx;
        List<Bitmap> pics;

        public ImagemAdapter(Context c, List<Bitmap> pics) {
            ctx = c;
            this.pics = pics;
        }

        @Override
        public int getCount() {

            return pics.size();
        }

        @Override
        public Object getItem(int position) {
            return pics.get(position);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent){
            if(convertView == null){
                int arquivoLayout = R.layout.adp_galeria;
                LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(arquivoLayout, null);
                ImageView img = ((ImageView)convertView.findViewById(R.id.imgProd));            
                img.setImageBitmap(pics.get(position));
            }
            return convertView;
        }

}

another strange thing is, the convertView on the adapter is ALWAYS null.

EDIT:

I think the problem is that bitmap retains in the memory. When the onCreateView of the Fragment is called, i populate a List with the images i should show and when the onDestroyView of fragment is called, I do this:

for(int i =0; i< imagemBit.size(); i++){
    Bitmap bmp = imagemBit.get(i);
    bmp.recycle();
    bmp = null;
}
imagemBit.clear();

BUT: When the onCreateView is called again (the user returned to a previous page) when I try to populate again the list the app crashes with OutOfMemory Exception.

JannGabriel
  • 302
  • 5
  • 14

2 Answers2

2

Please look at this answer
I experienced same problems on downloading and showing many images with caching in memory. Make sure that no more than some number of images (depending on size) staying in memory.

Community
  • 1
  • 1
ooops
  • 326
  • 2
  • 14
  • how do I deallocate the image from memory? – JannGabriel May 22 '13 at 20:04
  • Since memory for decoding bitmaps is allocated natively instead of allocating in heap, it is more complicated for GC to free it. Fortunately Bitmap has recycle() method which deallocates memory instantly. – ooops May 22 '13 at 20:13
  • i'm using the recycle() inside a for loop to deallocate each iten in the list, and them i'm using list.clear(). But still having OutOfMemory exception – JannGabriel May 22 '13 at 20:18
  • Your edited question is what now I am writing about :) "the convertView on the adapter is ALWAYS null" is bad, because you are not utilizing the old Views with Bitmaps. You should properly override getViewTypeCount() and getItemViewType() methods. Please look at this http://stackoverflow.com/a/5301093/2410326 – ooops May 22 '13 at 20:36
  • Sorry, it seems that I gave you irrelevant link. Base adapter already have correct implementation of that methods. But you definitely need to look at your convertView that allways is null. Looks like this is known bug of Gallery https://code.google.com/p/android/issues/detail?id=3376 . Can you check your code on higher version Android ? – ooops May 22 '13 at 20:51
  • Despite I changed the Gallery for ViewPager, this was the best answer for the problem. – JannGabriel May 23 '13 at 13:40
  • So what did extactly caused the problem? Non-avalability of existing views(with bitmaps) conversion? – ooops May 23 '13 at 14:33
  • 1
    That was a lot of things. First the non-avalability of the conversion, second the size of the picture (resizing it consumed less memory) and third the release of the memory – JannGabriel May 23 '13 at 16:44
1

Where your app crashes at your code?

I think that after you close your app, 'pics' is still keeping a reference to the bitmaps, and that's why the GC doesn't release the bitmaps. You must release the bitmaps, when your app stops or before creating the new bitmaps.

Alex248
  • 427
  • 4
  • 15
  • thats right. it keep the reference, because it crashes when trying to load bitmapfactory again. I tryed to add a lot of photos and it ALWAYS crashes. I think the other problem is with the size of images. Do you know how to handle a big amount of large images? – JannGabriel May 22 '13 at 14:02
  • You have to use some images loader that runs in backgroud. If your images are from Network you can use android query : https://code.google.com/p/android-query/downloads/detail?name=android-query-full.0.24.3.jar. read here https://code.google.com/p/android-query/#Image_Loading. if not, maybe this lib can help you. if not, the consept that i recommend is: use an array of bitmap, array of bitmap details. on start recycle them if they are not null. Use AsyncTask to create the bitmaps by yous bitmaps details. – Alex248 May 22 '13 at 14:30
  • man, I`m using and array of bitmap create inside the onCreateView of the Fragment and destroying it onDestroyView. It crashes before open the application. What am i doing wrong? – JannGabriel May 22 '13 at 17:13
  • where exactly your crash happens? can you show me the full log? – Alex248 May 23 '13 at 11:17
  • another thing. I don't think that this is a good idea to load many big images from getView. This method called many times and you must be careful there. To check this, Here : 'img.setImageBitmap(pics.get(position));' put some resource image instead, the same one. if it won't crash then the problem is with loading the images from getView. – Alex248 May 23 '13 at 11:27
  • If using image from resource it works perfectly. I changed the gallery for viewpager and everything worked just great! I think the problem is using Gallery... – JannGabriel May 23 '13 at 13:38