【问题标题】:Android OOM with BitmapAndroid OOM 与位图
【发布时间】:2017-02-16 11:37:10
【问题描述】:

所以我在 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 上的特定原因导致它,但这里的任何帮助将不胜感激。 谢谢

【问题讨论】:

  • 你也可以发布日志吗?

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


【解决方案1】:

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

请参阅 here 了解实现细节

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多