Android performance with inBitmap
August 5, 2015 7:38 am
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
Category: Performance, tutorials
Tags: android, bitmap, development, gallery, how-to, image, inBitmap, performance, recyclerview, reusable, tutorial, video