带有Bitmap的Android OOM

时间:2016-10-07 12:51:48

标签: android bitmap out-of-memory android-custom-view

所以我在Crashlytics看到我们有很多崩溃是由OOM引起的位图造成的。 似乎60%的产品来自6.0.1的Galaxy S7 Edge设备。 我们所拥有的是一个带有2个图像的着陆屏幕,一个从右向左滚动的背景图像,然后被重新创建以给予他们对前景图像移动的印象。

在Fabric日志的顶部,它表示在课堂上出现错误。 然而,在堆栈中进一步下降,我发现它似乎是由我们的ParallaxImageView引起的。 在这里我们这样做:

private void initializeCustomAttrs(Context context, AttributeSet attrs) {
    TypedArray attributes = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.ParallaxImageView,
            0, 0);

    try {
        speed = attributes.getDimension(R.styleable.ParallaxImageView_speed, 10);
        bitmap = BitmapFactory.decodeResource(getContext().getResources(),
                attributes.getResourceId(R.styleable.ParallaxImageView_src, 0));

    } finally {
        attributes.recycle();
    }
}

我不确定这种情况是否正确,或者其他一种方法是否会导致这种情况发生。 我们也有这些方法:

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (canvas == null || bitmap == null) {
        return;
    }

    canvas.getClipBounds(clipBounds);

    while (offset <= -bitmap.getWidth()) {
        offset += bitmap.getWidth();
    }

    float left = offset;
    while (left < clipBounds.width()) {
        int width = bitmap.getWidth();
        canvas.drawBitmap(bitmap, getBitmapLeft(width, left), 0, null);
        left += width;
    }

    if (isAnimating && speed != 0) {
        offset -= abs(speed);
        postInvalidateOnAnimation();
    }
}

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    start();
}

@Override
public void start() {
    if (!isAnimating) {
        isAnimating = true;
        postInvalidateOnAnimation();
    }
}

@Override
public void stop() {
    if (isAnimating) {
        isAnimating = false;
        invalidate();
    }
}

 private Bitmap scaleToFitHeight(Bitmap bitmap, int height) {
    if (height > 0) {
        float factor = height / (float) bitmap.getHeight();

        Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * factor), height, true);
        if (!newBitmap.equals(bitmap)) {
            bitmap.recycle();
        }

        return newBitmap;
    }
    return bitmap;
}

private float getBitmapLeft(float layerWidth, float left) {
    if (speed < 0) {
        return clipBounds.width() - layerWidth - left;
    } else {
        return left;
    }
}

我不知道是什么导致了这个问题,因为我认为我们正在正确解码和回收。不确定它是否可能是导致它的6.0.1特定的东西,但是在这里的任何帮助将不胜感激。 感谢

1 个答案:

答案 0 :(得分:0)

您没有正确解码图像,首先应检查尺寸,然后使用比例因子对其进行解码。假设您的图像是2000 x 2000,压缩版本可能很容易&lt; 1mb但是将它解压缩成位图需要2000 * 2000 * 4字节= 16mb(!)
如果你确定图像大小是可管理的但是因为你得到OOM我可能不是这种情况我猜它是不是

请参见here了解实施细节