首页 > 代码库 > 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错误的解决