位图decodeResource - 三星S5上的内存不足崩溃

时间:2014-12-03 11:16:36

标签: android bitmap crash

我在尝试显示背景图片时每次使用Galaxy S5时都会遇到崩溃。

此背景位于xxhdpi资源文件夹中,大小与S5屏幕(1080x1920)相同,因此我不需要调用" createScaledBitmap"用于缩放它。该图像的分辨率为JPG 96dpi。

当调用decodeResource时......崩溃!这怎么可能?我唯一能够加载这个"超级强大的#34;设备。

感谢!!!

在我的代码下面(S5的比例= 1):

public static Bitmap decodeBitmapFromResource(Resources res, int resId, float scale) {

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    options.inSampleSize = calculateInSampleSize(options, 
            (int)(options.outWidth*scale), 
            (int)(options.outHeight*scale));

    options.inJustDecodeBounds = false;

    if (scale > 1) {
        Bitmap bitmap = BitmapFactory.decodeResource(res, resId);
        return Bitmap.createScaledBitmap(bitmap, (int)(options.outWidth*scale), 
                (int)(options.outHeight*scale), true);
    }

    return BitmapFactory.decodeResource(res, resId, options);
}

3 个答案:

答案 0 :(得分:1)

试试这个

public static Bitmap decodeBitmapFromResource(String pathName, int reqWidth, int  reqHeight) {
    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathName, options);
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    // return BitmapFactory.decodeResource(res, resId, options);
    return BitmapFactory.decodeFile(pathName, 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) {

        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}

答案 1 :(得分:1)

我也经常多次面对这个问题......

尝试使用此代码..

    private Bitmap decodeFile(File f) throws IOException {
    Bitmap b = null;

    DisplayMetrics metrics = new DisplayMetrics();
    getActivity().getWindowManager().getDefaultDisplay()
            .getMetrics(metrics);

    // Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;

    o.inDither = false; // Disable Dithering mode
    o.inPurgeable = true; // Tell to gc that whether it needs free memory,
                            // the Bitmap can be cleared
    o.inInputShareable = true;

    FileInputStream fis = new FileInputStream(f);
    BitmapFactory.decodeStream(fis, null, o);
    fis.close();

    int scale = 1;
    if (o.outHeight > metrics.heightPixels
            || o.outWidth > metrics.widthPixels) {
        scale = (int) Math.pow(
                2,
                (int) Math.ceil(Math.log(metrics.heightPixels
                        / (double) Math.max(o.outHeight, o.outWidth))
                        / Math.log(0.5)));
    }

    // Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    fis = new FileInputStream(f);
    b = BitmapFactory.decodeStream(fis, null, o2);
    fis.close();

    return b;
}

并处理一些事情,例如在使用等之后将每个位图设为null。

答案 2 :(得分:0)

在应用程序标记的Manifest文件中添加此行。它并没有解决问题只是让你的应用程序有更多的内存:

 android:largeHeap="true"

<强>更新

然而,使用largeHeap并不是一个好的解决方案。这是谷歌关于此的文档。

  

但是,请求大堆的功能仅适用于a   一小组应用程序,可以证明需要消耗更多的RAM(例如   作为一个大型照片编辑应用程序)。 永远不要求大堆   因为你的内存不足而需要快速修复 - 你应该这样做   只有当你确切知道所有记忆的存在时才使用它   分配以及必须保留的原因。然而,即使你有信心   你的应用程序可以证明大堆的合理性,你应该避免请求它   尽可能的。使用额外的内存将越来越多   因为垃圾而损害整体用户体验   收集将花费更长时间,系统性能可能会更慢   任务切换或执行其他常见操作。

关于加载位图:

  

加载位图时,只能以您需要的分辨率将其保存在RAM中   对于当前设备的屏幕,如果原始屏幕缩小它   位图是一个更高的分辨率。请记住,位图的增加   分辨率导致所需的内存相应(增加2),   因为X和Y尺寸都增加了。

看一下这个页面并不错,它解释了管理内存的方法:

How Your App Should Manage Memory

所以我认为我的最后一个答案不是一个好的解决方案,您可能会重新考虑加载图像的策略。希望这个答案可以帮助你;)