0

I have someone getting an error while loading a bunch of images on my app and I'm not sure whats causing it.

This is the error he gets. LINE 135 is at the bottom.
I'm thinking he is running out of memory on his phone. He is using a Desire HD which was made in 2010. What this method does is get an image from the server and keep it in a hash map. Along with displaying it onto the screen. Any ideas on how I could prevent this OUTMEMORYERROR?

I was thinking setting up a counter that just clears the hash map if there are over 20 images.

Logcat:

java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657)
at com.codalata.craigslistchecker.GETTHEIMAGE$ITask.doInBackground(GETTHEIMAGE.java:135)
at com.codalata.craigslistchecker.GETTHEIMAGE$ITask.doInBackground(GETTHEIMAGE.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)

Code:

 public class GETTHEIMAGE {

private HashMap<String, Drawable> ICache;
private static Drawable DefIcon = null;
private BaseAdapter adapt;
private ItemView item;
private int num = 0;

public GETTHEIMAGE(Context c) {
    ICache = new HashMap<String, Drawable>();
}

public Drawable GetTheImagedata(
        com.codalata.craigslistchecker.Favorites.TheListAdapter theListAdapter,
        ImageView ICON_IMG) {
    this.adapt = theListAdapter;
    String url = (String) ICON_IMG.getTag();
    if (ICache.containsKey(url)) {
        return ICache.get(url);
    } else {
        new ITask().execute(url);
        return DefIcon;
    }
}

public Drawable GetTheImagedata(TheListAdapter adapter, ImageView ICON_IMG) {
    this.adapt = adapter;
    String url = (String) ICON_IMG.getTag();
    if (ICache.containsKey(url)) {
        return ICache.get(url);
    } else {
        new ITask().execute(url);
        return DefIcon;
    }
}

public Drawable GetTheImagedata2(ItemView itemView, String string) {
    this.item = itemView;
    String url = string;
    if (ICache.containsKey(url)) {
        return ICache.get(url);
    } else {
        new ITask2().execute(url);
        return DefIcon;
    }
}

private class ITask2 extends AsyncTask<String, Void, Drawable> {
    private String Nick;

    @Override
    protected Drawable doInBackground(String... params) {
        Nick = params[0];
        InputStream isImage = null;
        try {
            URL url = new URL(Nick);
            isImage = url.openStream();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Drawable.createFromStream(isImage, "Nick");
    }

    @Override
    protected void onPostExecute(Drawable result) {
        super.onPostExecute(result);
        if (num == 0) {
            item.ivItemimage1.setImageDrawable(result);
        }
        if (num == 1) {
            item.ivItemimage2.setImageDrawable(result);
        }
        if (num == 2) {
            item.ivItemimage3.setImageDrawable(result);
        }
        if (num == 3) {
            item.ivItemimage4.setImageDrawable(result);
        }
        if (num == 4) {
            item.ivItemimage5.setImageDrawable(result);
        }
        if (num == 5) {
            item.ivItemimage6.setImageDrawable(result);
        }
        if (num == 6) {
            item.ivItemimage7.setImageDrawable(result);
        }
        if (num == 7) {
            item.ivItemimage8.setImageDrawable(result);
        }
        if (num == 8) {
            item.ivItemimage9.setImageDrawable(result);
        }
        if (num == 9) {
            item.ivItemimage10.setImageDrawable(result);
        }
        num++;
    }
}

private class ITask extends AsyncTask<String, Void, Drawable> {
    private String Nick;

    @Override
    protected Drawable doInBackground(String... params) {
        Nick = params[0];
        InputStream isImage = null;
        try {
            URL url = new URL(Nick);
            isImage = url.openStream();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try{
 LINE 135 ----->            return Drawable.createFromStream(isImage, "Nick");
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Drawable result) {
        super.onPostExecute(result);
        synchronized (this) {
            ICache.put(Nick, result);
        }
        adapt.notifyDataSetChanged();
    }
}
 }
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Xjasz
  • 1,238
  • 1
  • 9
  • 21
  • 20 images. what's the size of each image? if its too large you will need to scale them down. Also its better to cache the images on sdcard/internal phone memory. – Raghunandan Jul 20 '13 at 06:47
  • Some of the images are small like 200x200x and some are large like 1000x1000x the problem is I need to get rid of them immediately. Because the guys phone is very old and cannot handle a lot of images in cache. – Xjasz Jul 20 '13 at 07:29

2 Answers2

1

You need to scale down the bitmaps and load a scaled down version in memory.

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

Use appropriateBitmapFactory.decode method as needed.

Here's an Example:

Out of Memory error with Bitmap

Note: As of Android 3.0 (API Level 11), the pixel data is stored on the Dalvik heap along with the associated bitmap.

On Android 2.3.3 (API level 10) and lower, using recycle() is recommended. If you're displaying large amounts of bitmap data in your app, you're likely to run into OutOfMemoryError errors. The recycle() method allows an app to reclaim memory as soon as possible.

Android 3.0 (API Level 11) introduces theBitmapFactory.Options.inBitmap field. If this option is set, decode methods that take the Options object will attempt to reuse an existing bitmap when loading content. This means that the bitmap's memory is reused, resulting in improved performance, and removing both memory allocation and de-allocation.

http://developer.android.com/training/displaying-bitmaps/manage-memory.html

Community
  • 1
  • 1
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • @Xjasz also check this lazy loading http://stackoverflow.com/questions/16789676/caching-images-and-displaying/16978285#16978285 – Raghunandan Jul 20 '13 at 06:59
0

in your first AsyncTask class num++; always increasing, so at some value it goes beyond memory space allocated for this program, you should put a control for that

Onur A.
  • 3,007
  • 3
  • 22
  • 37
  • That Async class ITask2 is for something else I max it at 10 because no one can ever gets to 10 images. ITask is where this error is happening. i'll remove some code it looks messy – Xjasz Jul 20 '13 at 06:52
  • @Xjasz If you're displaying large amounts of bitmap data in your app, you're likely to run into OutOfMemoryError errors. If the images are too large then you are likely to run into memory leaks. So scale down your bitmaps. 20 images should not lead into OOM. http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html. also check caching bitmaps in the docs. – Raghunandan Jul 20 '13 at 06:54
  • you sure about no one can gets to 10? also even if no one can get to 10, number of images below 10 also can lead to a OutOfMemory, you should reduce size/resolution of your images files – Onur A. Jul 20 '13 at 06:55
  • @Xjasz Also you can consider lazy loading of images if you are displaying images in a listview or gridview http://stackoverflow.com/questions/16789676/caching-images-and-displaying/16978285#16978285 – Raghunandan Jul 20 '13 at 06:58
  • Yea I was thinking of using lazy list view a month ago. These images are loaded up in a list view but this list view contains 200 items. After the guy scrolls through about 30 items all of the past images that are not even in view anymore are still in memory and need to be removed because his old phone is completely out of memory . I'm looking for a way now to recycle these images out if they are not in view. – Xjasz Jul 20 '13 at 07:10