11

My app main purpose is to display images in following fashion as shown in image

enter image description here

private void setSelectedImage(int selectedImagePosition) 
{

    BitmapDrawable bd = (BitmapDrawable) drawables.get(selectedImagePosition);
    Bitmap b = Bitmap.createScaledBitmap(bd.getBitmap(), (int) (bd.getIntrinsicHeight() * 0.9), (int) (bd.getIntrinsicWidth() * 0.7), false);
    selectedImageView.setImageBitmap(b);
    selectedImageView.setScaleType(ScaleType.FIT_XY);

}

Detailed code can be find here

exception is thrown at following line

Bitmap b = Bitmap.createScaledBitmap(bd.getBitmap(), (int) (bd.getIntrinsicHeight() * 0.9), (int) (bd.getIntrinsicWidth() * 0.7), false);

Above function is called from onItemSelected. **The app still works well on 2.2 and 2.3, but throws exception immediately on 4.1 Above code works fine, but throws following exception. I didnot see any crashes in 2.2 and 2.3, but it immedidately crashes in 4.1 Is there any major difference of memory management in Jelly beans? **:

java.lang.OutOfMemoryError
AndroidRuntime(2616):   at android.graphics.Bitmap.nativeCreate(Native Method)
AndroidRuntime(2616):   at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
AndroidRuntime(2616):   at android.graphics.Bitmap.createBitmap(Bitmap.java:586) 
AndroidRuntime(2616):   at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:466)
AndroidRuntime(2616):   at com.rdx.gallery.GalleryDemoActivity.setSelectedImage(GalleryDemoActivity.java:183)
Rohit
  • 6,941
  • 17
  • 58
  • 102

3 Answers3

25

It's important to note that following code can cause Exception:

Bitmap bitmap = Bitmap.createScaledBitmap(oldBitmap, newWidth, newHeight, true); 
oldBitmap.recycle();

Proper is:

Bitmap bitmap = Bitmap.createScaledBitmap(oldBitmap, newWidth, newHeight, true); 
if (oldBitmap!= bitmap){
     oldBitmap.recycle();
}

because documentation says:

If the specified width and height are the same as the current width and height of the source btimap, the source bitmap is returned and now new bitmap is created.

Malachiasz
  • 7,126
  • 2
  • 35
  • 49
  • This code can still trigger exceptions if the bitmap was already recycled for any reason, you need to add this to the check: && !oldBitmap.isRecycled() – Yoann Hercouet Jun 23 '15 at 08:23
  • In which implementation of Bitmap class it is necessary? Because not in 5.1.0_r1, as the method checks it istelf: "if (!mRecycled && mFinalizer.mNativeBitmap != 0) " http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.0_r1/android/graphics/Bitmap.java#Bitmap.recycle%28%29 – Malachiasz Jun 24 '15 at 09:25
13

http://www.youtube.com/watch?v=_CruQY55HOk. After andorid 3.0 bitmaps pixel data are stored on the heap. It seems you are exceeding heap memory size. Just because your app requires large heap do not use large heap. More the size of heap, more regular garbage collections. The video has a good explanation on the topic.

Also recycle bitmaps when not in use. Garbage collections on heap is done my mark and sweep , so when you recycle bitmaps it free's memory. So your heap size will not grow and run out of memory.

 bitmap.recycle();

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. Documentation on loading bitmaps efficiently. Have a look at loading scaled down version in memory.

Apart form this you can use Universal Image Loader. https://github.com/nostra13/Android-Universal-Image-Loader.

https://github.com/thest1/LazyList. Lazy Loading of Images.

Both use caching.

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
5

You are trying to access more memory then you have. Try to use

 BitmapFactory.Options opts=new BitmapFactory.Options();
        opts.inDither=false;                    
        opts.inSampleSize = 8;                   
        opts.inPurgeable=true;                 
        opts.inInputShareable=true;             
        opts.inTempStorage=new byte[16 * 1024]; 

Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.h1)
        , 65,65, true),

Also look at below links to increase memory

http://developer.android.com/reference/android/R.styleable.html#AndroidManifestApplication_largeHeap

Detect application heap size in Android

EDIT 1

try to use nostras image downloader, you can use it to show image in local storage. And it manages memory very well ...

https://github.com/nostra13/Android-Universal-Image-Loader

Community
  • 1
  • 1
Talha
  • 12,673
  • 5
  • 49
  • 68