Design to Handle Large Bitmaps
The Android system has a limited amount of memory, so downloadingand storing high-resolution images can often cause out-of-memoryerrors in your app. To avoid this, follow these tips:
- Load images only when they'redisplayed on the screen. For example, when displaying multipleimages in a
GridView
or Gallery
,only load an image whengetView()
iscalled on the View's Adapter
. - Call
recycle()
on Bitmap
viewsthat are no longer needed. - Use
WeakReference
forstoring references to Bitmap
objectsin an in-memory Collection
. - If you fetch images from thenetwork, use
AsyncTask
tofetch them and store them on the SD card for faster access. Neverdo network transactions on the application's UI thread. - Scale down really large images toa more appropriate size as you download them; otherwise,downloading the image itself may cause an "Out of Memory"exception. Here is sample code that scales down images whiledownloading:
// Get the source image's dimensions BitmapFactory.Options options = new BitmapFactory.Options(); // This does not download the actual image, just downloads headers. options.inJustDecodeBounds = true; BitmapFactory.decodeFile(IMAGE_FILE_URL, options); // The actual width of the image. int srcWidth = options.outWidth; // The actual height of the image. int srcHeight = options.outHeight; // Only scale if the source is bigger than the width of the destination view. if(desiredWidth > srcWidth) desiredWidth = srcWidth; // Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2. int inSampleSize = 1; while(srcWidth / 2 > desiredWidth){ srcWidth /= 2; srcHeight /= 2; inSampleSize *= 2; } float desiredScale = (float) desiredWidth / srcWidth; // Decode with inSampleSize options.inJustDecodeBounds = false; options.inDither = false; options.inSampleSize = inSampleSize; options.inScaled = false; // Ensures the image stays as a 32-bit ARGB_8888 image. // This preserves image quality. options.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options); // Resize Matrix matrix = new Matrix(); matrix.postScale(desiredScale, desiredScale); Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0, sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true); sampledSrcBitmap = null; // Save FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE); scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); scaledBitmap = null;