在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;
}