Catching OutOfMemoryError in decoding Bitmap
14,041
Solution 1
It's good practice to catch it once and give decodeFile
another chance. Catch it and call System.gc()
and try decoding again. There is a high probability that it will work after calling System.gc()
.
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
bitmap = BitmapFactory.decodeFile(file, options);
} catch (OutOfMemoryError e) {
e.printStackTrace();
System.gc();
try {
bitmap = BitmapFactory.decodeFile(file);
} catch (OutOfMemoryError e2) {
e2.printStackTrace();
// handle gracefully.
}
}
Solution 2
I did something like this: I catch the error only for try to scale down the image until it works. Eventually it can not work at all; then returns null; otherwise, in success, returns the bitmap.
Outside I decide what to do with the bitmap whether it's null or not.
// Let w and h the width and height of the ImageView where we will place the Bitmap. Then:
// Get the dimensions of the original bitmap
BitmapFactory.Options bmOptions= new BitmapFactory.Options();
bmOptions.inJustDecodeBounds= true;
BitmapFactory.decodeFile(path, bmOptions);
int photoW= bmOptions.outWidth;
int photoH= bmOptions.outHeight;
// Determine how much to scale down the image.
int scaleFactor= (int) Math.max(1.0, Math.min((double) photoW / (double)w, (double)photoH / (double)h)); //1, 2, 3, 4, 5, 6, ...
scaleFactor= (int) Math.pow(2.0, Math.floor(Math.log((double) scaleFactor) / Math.log(2.0))); //1, 2, 4, 8, ...
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds= false;
bmOptions.inSampleSize= scaleFactor;
bmOptions.inPurgeable= true;
do
{
try
{
Log.d("tag", "scaleFactor: " + scaleFactor);
scaleFactor*= 2;
bitmap= BitmapFactory.decodeFile(path, bmOptions);
}
catch(OutOfMemoryError e)
{
bmOptions.inSampleSize= scaleFactor;
Log.d("tag", "OutOfMemoryError: " + e.toString());
}
}
while(bitmap == null && scaleFactor <= 256);
if(bitmap == null)
return null;
For example, with an image of 3264x2448, the loop iterates 2 times on my phone, and then it works.
Related videos on Youtube
Author by
bitbybit
Updated on June 10, 2022Comments
-
bitbybit about 2 years
Is it a good practice to catch OutOfMemoryError even you have tried some ways to reduce memory usage? Or should we just not catching the exception? Which one is better practice?
try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; bitmap = BitmapFactory.decodeFile(file, options); } catch (OutOfMemoryError e) { e.printStackTrace(); }
Thanks
-
Kai Sternad almost 13 yearshere's a discussion on the topic: comments.gmane.org/gmane.comp.handhelds.android.devel/100621
-
Raedwald over 8 yearsPossible duplicate of Catching java.lang.OutOfMemoryError?
-
-
bitbybit almost 13 yearsGood catch about the options. Thanks
-
bitbybit almost 13 yearsCalling System.gc() may not be good idea, http://code.google.com/p/android/issues/detail?id=8488#c80, anyway, thanks
-
Ron almost 13 yearsHere you have no worries with that, as you have not loaded the bitmap yet. So its safe to call GC. Just be sure you call
bitmap.recycle()
when you are finished with it. -
Edwin Evans over 11 yearsWhat should you do for "handle gracefully"? I'm not sure how to explain this to users in a friendly manner. Tell them to go to other apps and click Back? Ask them to Reboot?
-
Ron over 11 yearsProbably you should try with a higher
inSampleSize
value the second time. If it doesn't work even after that then you can display a message telling user that the image load operation failed and should try the same actions again.. -
user276648 over 9 yearsYou could also try adding android:largeHeap="true" in your manifest if you can't/don't want to use a higher inSampleSize.
-
thib_rdr over 8 yearsIt seems like a good solution, I would like to try it, but cant figure out what w and h variables are at the 7th line ?
-
jsanmarb over 8 years@GaryHost: w and h are the width and height of the ImageView where we will place the Bitmap. Answer updated.
-
thib_rdr over 8 yearsThanks men, I adopted your solution :)