在Android中,對圖片使用的記憶體是有限制的,載入的圖片過大便出導致OOM問題。映像在載入過程中,是把所有像素(即長*寬)載入到記憶體中,如果圖片過大,便會導致java.lang.OutOfMemoryError問題,因此,在使用時要要加以注意。
private static int MAX_IMAGE_DIMENSION = 720; public Bitmap decodeFile(String filePath) throws IOException { Uri photoUri = Uri.parse(filePath); InputStream is = this.getContentResolver().openInputStream(photoUri); BitmapFactory.Options dbo = new BitmapFactory.Options(); dbo.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, dbo); is.close(); int rotatedWidth, rotatedHeight; rotatedWidth = dbo.outWidth; rotatedHeight = dbo.outHeight; Bitmap mCurrentBitmap = null; is = this.getContentResolver().openInputStream(photoUri); if (rotatedWidth > MAX_IMAGE_DIMENSION || rotatedHeight > MAX_IMAGE_DIMENSION) { float widthRatio = ((float) rotatedWidth) / MAX_IMAGE_DIMENSION; float heightRatio = ((float) rotatedHeight) / MAX_IMAGE_DIMENSION; float maxRatio = Math.max(widthRatio, heightRatio); // Create the bitmap from file BitmapFactory.Options options = new BitmapFactory.Options(); // 1.換算合適的圖片縮放值,以減少對JVM太多的記憶體請求。 options.inSampleSize = (int) maxRatio; // 2. inPurgeable 設定為 true,可以讓java系統, 在記憶體不足時先行回收部分的記憶體 options.inPurgeable = true; // 與inPurgeable 一起使用 options.inInputShareable = true; // 3. 減少對Aphla 通道 options.inPreferredConfig = Bitmap.Config.RGB_565; try { // 4. inNativeAlloc 屬性設定為true,可以不把使用的記憶體算到VM裡 BitmapFactory.Options.class.getField("inNativeAlloc").setBoolean(options, true); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } // 5. 使用decodeStream 解碼,則利用NDK層中,利用nativeDecodeAsset() // 進行解碼,不用CreateBitmap mCurrentBitmap = BitmapFactory.decodeStream(is, null, options); } else { mCurrentBitmap = BitmapFactory.decodeStream(is); } return mCurrentBitmap; }