首页 > 代码库 > android开发步步为营之50:android关于加载大图片java.lang.OutOfMemoryError错误的解决
android开发步步为营之50:android关于加载大图片java.lang.OutOfMemoryError错误的解决
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html 官方有一篇文章是如下这么解决的,通过Resource加载后压缩图片大小
//方法一:通过Resource加载
mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
如果不是通过Resource,而是通过Drawable对象,比如获取手机所有安装的应用图标,通过下面这张方法来压缩图片
//方法二:通过Drawable对象加载
//获取压缩后的图标
private Drawable getAppIcon(PackageManager pm, ApplicationInfo applicationInfo) {
try {
//oom报错,采用下面的方法
Drawable drawable = pm.getApplicationIcon(applicationInfo);
Bitmap bm = CommonUtils.drawableToBitmap(drawable);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] data = http://www.mamicode.com/baos.toByteArray();
//压缩前
int size1=bm.getByteCount();
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, opts);
opts.inSampleSize = computeSampleSize(opts, -1, 100 * 100);
//这里一定要将其设置回false,因为之前我们将其设置成了true
opts.inJustDecodeBounds = false;
Bitmap bmNew =BitmapFactory.decodeByteArray(data, 0, data.length, opts);
//压缩后,测试过4194304Byte的压缩成16384Byte压缩效果明显
int size2=bmNew.getByteCount();
return new BitmapDrawable(bmNew);
//end
}catch(Exception e)
{
Log.e("DataCenter.getAppIcon.Exception", "Exception", e);
}
catch (OutOfMemoryError e) {
// TODO: handle exception
Log.e("DataCenter.getAppIcon.OutOfMemoryError", "OutOfMemoryError", e);
//图片太大就换一个默认的小图标给用户
return new BitmapDrawable(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher_default));
}
return null;
}
public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);
int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}
private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}
public static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
//canvas.setBitmap(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
BitmapFactory提供多种Decode方法,大家根据需要来使用
android开发步步为营之50:android关于加载大图片java.lang.OutOfMemoryError错误的解决