Android performance with inBitmap

Reusing bitmap with android's inBitmap

Describes how to reuse bitmaps evicted from the memory cache, therefore saving on bitmap allocations, deallocations overheads.

In the Android performance with inBitmap tutorial we add the BitmapFactory.Option’s inBitmap flag which can be used for bitmaps that have been evicted from the memory cache but not yet deallocated.

This is only supported for android versions Honeycomb or later.

Implementation

Create a Set of SoftReferenced Bitmaps

CamaraIntentActivity

private static Set<SoftReference<Bitmap>> mReuseableBitmap;

Initialise the Set

CamaraIntentActivity

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
            mReuseableBitmap = Collections.synchronizedSet(new HashSet<SoftReference<Bitmap>>());
        }

Add a bitmap to the Set when evicted from memory cache

CamaraIntentActivity

mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

            @Override
            protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
                super.entryRemoved(evicted, key, oldValue, newValue);
                if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
                    mReuseableBitmap.add(new SoftReference<Bitmap>(oldValue));
                }
            }

            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount() / 1024;
            }
        };

Provide methods for getting reusable bitmaps

CamaraIntentActivity

private static int getBytesPerPixel(Bitmap.Config config) {
       if(config == Bitmap.Config.ARGB_8888) {
           return 4;
       } else if(config == Bitmap.Config.RGB_565) {
           return 2;
       } else if(config == Bitmap.Config.ARGB_4444) {
           return 2;
       } else if(config == Bitmap.Config.ALPHA_8) {
           return 1;
       }
       return 1;
   }

   private static boolean canUseForBitmap(Bitmap candidate, BitmapFactory.Options options) {
       if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
           int width = options.outWidth / options.inSampleSize;
           int height = options.outHeight / options.inSampleSize;
           int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
           return byteCount <= candidate.getAllocationByteCount();
       }
       return candidate.getWidth() == options.outWidth &&
               candidate.getHeight() == options.outHeight &&
               options.inSampleSize == 1;
   }

   public static Bitmap getBitmapFromReuseableSet(BitmapFactory.Options options) {
       Bitmap bitmap = null;
       if(mReuseableBitmap != null && !mReuseableBitmap.isEmpty()) {
           synchronized (mReuseableBitmap) {
               Bitmap item;
               Iterator<SoftReference<Bitmap>> iterator = mReuseableBitmap.iterator();
               while(iterator.hasNext()) {
                   item = iterator.next().get();
                   if(item != null && item.isMutable()) {
                       if(canUseForBitmap(item, options)) {
                           bitmap = item;
                           iterator.remove();
                           break;
                       }
                   } else {
                       iterator.remove();
                   }
               }
           }
       }
       return bitmap;
   }

Create a method to add the reusable bitmap to BitmapFactory.Options inBitmap

BitmapWorkerTask

private static void addInBitmapOptions(BitmapFactory.Options options) {
       options.inMutable = true;
       Bitmap bitmap = CamaraIntentActivity.getBitmapFromReuseableSet(options);
       if(bitmap != null) {
           options.inBitmap = bitmap;
       }
   }

Call the addInBitmapOptions from the decodeBitmap method

private Bitmap decodeBitmapFromFile(File imageFile) {
       BitmapFactory.Options bmOptions = new BitmapFactory.Options();
       bmOptions.inJustDecodeBounds = true;
       BitmapFactory.decodeFile(imageFile.getAbsolutePath(), bmOptions);
       bmOptions.inSampleSize = calculateInSampleSize(bmOptions);
       bmOptions.inJustDecodeBounds = false;
       if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
           addInBitmapOptions(bmOptions);
       }
       return BitmapFactory.decodeFile(imageFile.getAbsolutePath(), bmOptions);
   }

Run the application

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>