Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Out of memory Exception, when dealing with bitmaps

Tags:

java

android

I am working on an application where i have images being downloaded asynchronously for SlideShows. One SlideShow contains 10 slides, hence 10 images are downloaded when slideshow is opened. After i scroll through 10-15 slideshows approximately i start getting memory warning and following Exception in the trace and app crashes.

Here is the trace:

12-23 12:23:53.124: ERROR/dalvikvm-heap(3067): 45850-byte external allocation too large for this process.
12-23 12:23:53.134: ERROR/dalvikvm(3067): Out of memory: Heap Size=13127KB, Allocated=11913KB, Bitmap Size=11407KB
12-23 12:23:53.134: ERROR/GraphicsJNI(3067): VM won't let us allocate 45850 bytes
12-23 12:23:53.134: DEBUG/skia(3067): --- decoder->decode returned false
12-23 12:23:53.134: WARN/dalvikvm(3067): threadid=46: thread exiting with uncaught exception (group=0x400259f8)
12-23 12:23:53.134: ERROR/AndroidRuntime(3067): FATAL EXCEPTION: Thread-1016
12-23 12:23:53.134: ERROR/AndroidRuntime(3067): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:468)
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:332)
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):     at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657)
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):     at com.nbcu.myApp.appsupport.AsyncImageLoader.loadImageFromUrl(AsyncImageLoader.java:98)
12-23 12:23:53.134: ERROR/AndroidRuntime(3067):     at com.nbcu.myApp.appsupport.AsyncImageLoader$2.run(AsyncImageLoader.java:70)
12-23 12:23:53.154: WARN/ActivityManager(96):   Force finishing activity com.nbcu.myApp.activities/com.nbcu.myApp.controllers.StoriesListController
12-23 12:23:53.224: ERROR/dalvikvm-heap(3067): 45850-byte external allocation too large for this process.
12-23 12:23:53.234: DEBUG/SurfaceFlinger(96): Layer::setBuffers(this=0x2fabc0), pid=96, w=1, h=1
12-23 12:23:53.234: ERROR/dalvikvm(3067): Out of memory: Heap Size=13127KB, Allocated=11948KB, Bitmap Size=11407KB
12-23 12:23:53.234: ERROR/GraphicsJNI(3067): VM won't let us allocate 45850 bytes
12-23 12:23:53.234: ERROR/Error(3067): Message = java.lang.OutOfMemoryError: bitmap size exceeds VM budget

The code where images are being downloaded is:

public void run() {

        Looper.prepare();
        for (int i = 0; i < slides.size(); i++) {
            try {

                final SlideShowItem story = slides.get(i);
                if (story.getImage() == null) {
                    Drawable cachedImage = Utils.database.getRSSImage(Constants.StoriesTable, story.getItemId());

                    if (cachedImage != null) {
                        story.setImage(cachedImage);

                    } else {
                        cachedImage = asyncImageLoader.loadDrawable(story.getImagePath(), new ImageCallback() {
                            public void imageLoaded(Drawable imageDrawable, String imageUrl) {


                                story.setImage(imageDrawable);
                                Utils.database.storeRSSItemImage(Constants.StoriesTable, imageDrawable, story.getItemId());
                            }
                        });
                    }
                }

                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        Looper.loop();
    }

Code for loadDrawable() is:

public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {

    final Handler handler = new Handler() {

        public void handleMessage(Message message) {

            imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
        }
    };
    new Thread() {

        public void run() {

                Drawable drawable = loadImageFromUrl(imageUrl);
                // System.out.println("image url: " + imageUrl);
                if (drawable != null)
                {
                    Message message = handler.obtainMessage(0, drawable);
                    handler.sendMessage(message);
                }
        }

    }.start();
    return null;
}

and the code for loadImageFromURL() is:

  public static Drawable loadImageFromUrl(String url) {

    Drawable image = null;

    try {
        InputStream in = (java.io.InputStream) new java.net.URL(url).getContent();
        if (in != null) {
            image = Drawable.createFromStream(in, "image");
        }
        in.close();

    } catch (Exception ex) {
        // ex.printStackTrace();
        Log.v("Exception ", "Asyn Image.In LoadImageFromURL Message: " + ex.toString());

    }
    return image;
}

Once images are downloaded they are cached. I am unable to find a workaround to avoid this exception. what could be the reason? I have also tried setting image views null when activity is destroyed but it has done nothing for me? Any help is appreciated. Thanks in advance.

like image 505
Usama Sarwar Avatar asked Dec 22 '22 04:12

Usama Sarwar


1 Answers

Android is a Mobile OS. It has a limited memory, so, you cannot cache all the slides.size(). I assume the size > 15. For example, im running a FastCV algorithm with a HD image as markers, 250000 x 180000 pixels and if i run the program on pc, work fine, if i do it on the mobile phone dont, because the memory is not enough.

I think you can solve the problem, if only caché 10 - 15 images, depends the size of them. If scroll, then cache new one in the memory already used.

like image 76
vgonisanz Avatar answered Dec 23 '22 17:12

vgonisanz