android - Android 位图出现奇怪的 OutOfMemoryError : Why does showing and then hiding the containing View avoid it?

标签 android camera out-of-memory

我是 stackoverflow 的常客,直到我遇到了一个我真的找不到任何现有问题的问题。这是我的第一个问题:

我正在构建一个相机应用程序,用户可以在其中拍摄几张照片,然后再继续下一步。我希望用户能够在相机阶段查看和删除图片,因此我编写了一个自定义 View ,以使用删除按钮显示已捕获图像的缩略图。这些“Thumbviews”包含在位于camerapreview-SurfaceView顶部的LinearLayout中,并且默认可见性为“GONE”。用户可以使用按钮切换可见性。

一切正常,但我有一个问题: 当我拍摄超过 10 张照片时,我会收到 OutOfMemoryError 错误。缩略图非常小,不会占用大量内存,而且我回收原始位图并在创建缩略图后执行 System.gc() 。 奇怪的是,当我按下将包含 LinearLayout 的可见性设置为“VISIBLE”并再次设置为“GONE”的按钮时,显然所有内存都被释放,我可以拍摄比 10 张更多的照片。 我尝试过切换代码中的可见性,但这不起作用,并且还破坏了绘图缓存。 除了按两次可见性按钮之外,还必须有另一种方法来释放内存;-)

这是 ThumbView 的代码:

public class ThumbView extends View {

private Bitmap mBitmap;
private Bitmap mScaledBitmap;
private int mWidth, mHeight, mPosX, mPosY;
static private Bitmap mDeleteBitmap;
private File mPreviewFile;
private File mFinalFile;
private Orientation mOrientation;
private boolean mRed;

public ThumbView(Context context, Bitmap bitmap, File previewFile, File finalFile, Orientation orientation) {
    super(context);
    mBitmap = bitmap;
    mPreviewFile = previewFile;
    mFinalFile = finalFile;
    mOrientation = orientation;
    if(mDeleteBitmap != null)
        return;
    mDeleteBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.deletebutton);
}

public void deleteFile()
{
    if(mPreviewFile != null && mPreviewFile.exists())
    {
        mPreviewFile.delete();
    }
    if(mFinalFile != null && mFinalFile.exists())
    {
        mFinalFile.delete();
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    mWidth  = MeasureSpec.getSize(widthMeasureSpec);
    setMeasuredDimension(mWidth, mWidth);

    if(mBitmap == null)
        return;
    mHeight = mWidth;

    float bitmapRatio = mBitmap.getWidth() / (float) mBitmap.getHeight();

    if(bitmapRatio > 1)
    {
        mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, mWidth,
                (int)(mWidth/bitmapRatio), true);
        mPosY = (mWidth-mScaledBitmap.getHeight())/2;
    }
    else
    {
        mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, (int)(mHeight*bitmapRatio),
                mHeight, true);
        mPosX = (mHeight-mScaledBitmap.getWidth())/2;
    }


    Matrix mtx = new Matrix();
    mtx.postRotate(-90);

    Bitmap b = Bitmap.createBitmap(mScaledBitmap, 0, 0, mScaledBitmap.getWidth(), mScaledBitmap.getHeight(), mtx, true);
    mScaledBitmap = b;
    b = null;

    mBitmap.recycle();
    mBitmap = null;
    System.gc();
}

public boolean deleteButtonPressed(float x, float y)
{
    Rect r = new Rect(mPosY, mPosX, mPosY+mDeleteBitmap.getWidth(),
            mPosX+mDeleteBitmap.getHeight());
    if(r.contains((int)x, (int)y))
    {
        return true;
    }
    return false;
}

public void setRed(boolean red)
{
    mRed = red;
    invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(mScaledBitmap, mPosY, mPosX, new Paint());
    canvas.drawBitmap(mDeleteBitmap, mPosY, mPosX, new Paint());
    if(mRed)
        canvas.drawColor(0x55FF0000);
}

}

最佳答案

“为什么它不会破裂”的答案很简单。当 subview (或容器)的可见性设置为 GONE 时,父布局(通常)将跳过它,甚至不费心渲染它。它不是“隐藏”的,它根本不存在。

如果你的缩略图确实是缩略图,你不应该耗尽内存,但是,我认为你没有对它们进行下采样(我可能是错的)。你如何向他们展示?您应该分享那段代码。 (新照片 -> 缩略图 -> ImageView )

关于android - Android 位图出现奇怪的 OutOfMemoryError : Why does showing and then hiding the containing View avoid it?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13073288/

相关文章:

android - React-native google signin 给出开发者错误

android - 获得平均值的最佳实践

iOS 如何访问原生方形照片设置?

javascript - Three.js 中 LookAt 和控件的冲突

c# - 使用 GC.AddMemoryPressure() 防止 OutOfMemoryException?

android - 我的 StateButton 状态没有更新我的 View

android - Facebook URL 方案不起作用 fb ://publish

android - 启动相机 Activity ,应用程序崩溃

java - java调试内存问题——理解freeMemory

perl - perl 在内存不足时是否有标准的行为方式?