Out of Memory Error While Loading Bitmaps

Out of Memory error with Bitmap

OutofMemory occurs when your app exceeds memory allocated in heap. The bitmap is too large to fit in memory ie heap. In such a case you run out of memory. You need to scale down the bitmap and then use the same. For that check the link below

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

There is also a blog @ http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html (avoiding memory leaks)

 public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);

//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;

//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

Quoting from the docs

The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class.

Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.

Also check this link for memory management.

https://www.youtube.com/watch?v=_CruQY55HOk

Out of memory issue while loading bitmaps in Android

Two (big) parts to my answer. The first is aimed more directly at your question, and the second part takes a step back as I share how I learned to implement my own solution that is aimed more at people running into this for the first time.

Don't use bitmap.recycle(), because you really shouldn't have to. While this clears the memory being used for that bitmap, you'll probably run into issues with the bitmap still being used somewhere.

You should also use WeakReference everywhere there's a possibility the object will hang onto a bitmap (loading Tasks, ImageViews, etc). From the documentation:

Weak references are useful for mappings that should have their entries removed automatically once they are not referenced any more (from outside). The difference between a SoftReference and a WeakReference is the point of time at which the decision is made to clear and enqueue the reference:
  • A SoftReference should be cleared and enqueued as late as possible, that is, in case the VM is in danger of running out of memory.
  • A WeakReference may be cleared and enqueued as soon as is known to be weakly-referenced.

Both should theoretically work, but we have a little problem: Java finalizers. They aren't guaranteed to run in time, and unfortunately, that's where our little friend Bitmap is clearing it's memory. If the bitmaps in question are created slowly enough, the GC probably has enough time to recognize our SoftReference or WeakReference object and clear it from memory, but in practice that's not the case.

The short of it is that it's extremely easy to outpace the Garbage Collector when working with objects that use finalizers like Bitmaps (I think some IO classes use them too). A WeakReference will help our timing problem a little bit better than a SoftReference. Yeah, it'd be nice if we could hold a bunch of images in memory for insane performance, but many Android devices simply don't have the memory to do this, and I've found that no matter how large the cache is you'll still run into this problem if you aren't clearing references as soon as humanly possible.

As far as your caching goes, the first change I'd make is to ditch your own memory cache class and just use the LruCache that's found in the Android compatibility library. Not that your cache has issues or anything, but it removes another point of headaches, it's already done for you, and you won't have to maintain it.

Otherwise, the biggest problem I see with what you have is that PhotoToLoad is holding a strong reference to an ImageView, but more of this whole class could use some tweaking.

A short but nicely-written blog post explaining a great method for holding references to correct ImageViews while downloading images can be found on Android's blog, Multithreading for Performance. You can also see this sort of practice in-use on Google's I/O app, whose source code is available. I expand on this a little in the second part.

Anyway, instead of trying to map the URLs being loaded to the ImageView it's intended for with a Collection as you're doing, following what's done on the blog post above is an elegant way to reference back to the ImageView in question while avoiding using a recycled ImageView by mistake. And of course, it's a good example of how the ImageViews are all weakly referenced, which means our Garbage Collector is allowed to free up that memory faster.

OK. Now the second part.

Before I continue on the issue more in general and get even more long-winded I'll say that you're on the right track, and that the rest of my answer probably treads on a lot of ground you already covered and know about, but I'm hoping it will also benefit someone newer at this so bear with me.

As you already know, this is a very common problem on Android with a fairly long explanation that's been covered before (shakes fist at finalizers). After banging my own head against the wall for hours on end, trying various implementations of loaders and cachers, watching the "heap growth/cleanup race" in logs endlessly, and profiling memory usage and tracing objects with various implementations until my eyes would bleed, a few things have become clear to me:

  1. If you find yourself trying to tell the GC when to fire, you're going down the wrong path.
  2. You're in for a world of pain if you try to call bitmap.recycle() on bitmaps that are used in the UI, such as ImageViews.
  3. A major reason this is such a headache is because there's way too much misinformation out there on this topic on how to solve the problem. So many of the tutorials or examples out there look good in theory, but in practice are absolute trash (confirmed by all the profiling and tracing I mentioned above). What a maze to navigate!

You have two options. The first is to use a well-known and tested library. The second is to learn the right way to accomplish this task and gain some insightful knowledge along the way. For some libraries you can do both options.

If you look at this question, you'll find a few libraries that will accomplish what you are trying to do. There's also a couple of great answers that point to very useful learning resources.

The route I took myself was the more difficult one, but I'm obsessed with understanding solutions and not simply just using them. If you want to go the same route (it's worth it), you should first follow Google's tutorial "Displaying Bitmaps Efficiently".

If that didn't take, or you want to study a solution used in practice by Google themselves, check out the utility classes that handle bitmap loading and caching in their I/O 2012 app. In particular, study the following classes:

  • DiskLruCache.java
  • ImageCache.java
  • ImageFetcher.java
  • ImageWorker.java
  • public static ImageFetcher getImageFetcher(final FragmentActivity activity) in UIUtils.java

And of course, study some of the Activities to see how they use these classes. Between the official Android tutorial and the I/O 2012 app, I was able to successfully roll my own to fit what I was doing more specifically and know what was actually happening. You can always study some of the libraries I mentioned in the question I linked to above as well to see a couple of slightly different takes.

out of memory error when using bitmap in recyclerview

Hey you don't have to decode drawable to bitmap.

you can do it like this.

imageview.setImageResource(R.drawable.whatever_the_image_is)

Hope this helps you

Out of memory error when loading bitmap from Uri

I read all the answers and this is what I am planning to do, tell me if it will work or not. In my Application class, in onCreate(), I store the device width and height in pixels in the SharedPreferences. In the modified code, I scale the bitmap according to the device pixels. Hope it will spare me the OOM error.

private static Bitmap getBitmapFromUri(@NonNull Context context, @NonNull Uri uri) throws IOException {

ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
assert parcelFileDescriptor != null;
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();

TinyDB tinyDB = new TinyDB(context);
int maxSize = Math.min(tinyDB.getInt(AppConstants.DEVICE_WIDTH, 720), tinyDB.getInt(AppConstants.DEVICE_HEIGHT, 1080));
int outWidth;
int outHeight;
int inWidth = image.getWidth();
int inHeight = image.getHeight();
if(inWidth > inHeight){
outWidth = maxSize;
outHeight = (inHeight * maxSize) / inWidth;
} else {
outHeight = maxSize;
outWidth = (inWidth * maxSize) / inHeight;
}

return Bitmap.createScaledBitmap(image, outWidth, outHeight, false);
}

Out of Memory Error while loading bitmaps

for quick fix you can add

android:largeHeap="true" in your manifest application tag

link here:

I face OOM problem for my table in kindle and nook

Heap size (large)
android:largeHeap="true"

there specification is mentioned to use larger heap link here:

edit: use Caching Bitmaps technique link here



Related Topics



Leave a reply



Submit